diff --git a/GAMEMASTER.md b/GAMEMASTER.md index 0bddb1f3..0baf3550 100644 --- a/GAMEMASTER.md +++ b/GAMEMASTER.md @@ -688,6 +688,11 @@ may not run any more, or will run strangely, which will make you sad. Adding the new gamedefs in will make you happy again ;) +### 5.1 Creating a new game rule set +1. Create a new directory $gamename +2. Copy basic/Makefile.inc to $gamename +3. Replace "basic" with $gamename +4. Add $gamename to Makefile $GAMES ## 6. World Creation Guide diff --git a/Makefile b/Makefile index 33199d66..e6d51ec3 100644 --- a/Makefile +++ b/Makefile @@ -6,124 +6,52 @@ # ---- ------ -------- # 2000/MAR/14 Davis Kulis Added the template code. # 2004/MAR/29 Jan Rietema Added/modified the gamesets +CXX ?= g++ +CXXFLAGS += -g -I. -I.. -Wall -std=c++11 -MP -MMD -O -GAME ?= standard +# allow substitution of dependency file +CXXBUILD = $(CXX) $(CXXFLAGS) -MF $(patsubst %.cpp,dep/%.d,$<) -c -o $@ $< -CPLUS = g++ -CC = gcc -CFLAGS = -g -I. -I.. -Wall -std=c++11 - -RULESET_OBJECTS = extra.o map.o monsters.o rules.o world.o - -ENGINE_OBJECTS = alist.o aregion.o army.o astring.o battle.o economy.o \ +OBJ := alist.o aregion.o army.o astring.o battle.o economy.o \ edit.o faction.o fileio.o game.o gamedata.o gamedefs.o gameio.o \ genrules.o i_rand.o items.o main.o market.o modify.o monthorders.o \ npc.o object.o orders.o parseorders.o production.o quests.o runorders.o \ shields.o skills.o skillshows.o specials.o spells.o template.o unit.o \ events.o events-battle.o events-assassination.o mapgen.o simplex.o namegen.o -OBJECTS = $(patsubst %.o,$(GAME)/obj/%.o,$(RULESET_OBJECTS)) \ - $(patsubst %.o,obj/%.o,$(ENGINE_OBJECTS)) - -$(GAME)-m: objdir $(OBJECTS) - $(CPLUS) $(CFLAGS) -o $(GAME)/$(GAME) $(OBJECTS) - -all: basic standard fracas kingdoms havilah neworigins - -arcadia: FORCE - $(MAKE) GAME=arcadia - -basic: FORCE - $(MAKE) GAME=basic - -standard: FORCE - $(MAKE) GAME=standard - -kingdoms: FORCE - $(MAKE) GAME=kingdoms - -fracas: FORCE - $(MAKE) GAME=fracas - -havilah: FORCE - $(MAKE) GAME=havilah - -neworigins: FORCE - $(MAKE) GAME=neworigins - -$(GAME)/$(GAME): FORCE - $(MAKE) GAME=$(GAME) - -all-clean: basic-clean standard-clean fracas-clean kingdoms-clean \ - havilah-clean neworigins-clean - -arcadia-clean: - $(MAKE) GAME=arcadia clean - -basic-clean: - $(MAKE) GAME=basic clean - -standard-clean: - $(MAKE) GAME=standard clean - -fracas-clean: - $(MAKE) GAME=fracas clean - -kingdoms-clean: - $(MAKE) GAME=kingdoms clean - -havilah-clean: - $(MAKE) GAME=havilah clean - -neworigins-clean: - $(MAKE) GAME=neworigins clean - -clean: - rm -f $(OBJECTS) - if [ -d obj ]; then rmdir obj; fi - if [ -d $(GAME)/obj ]; then rmdir $(GAME)/obj; fi - rm -f $(GAME)/html/$(GAME).html - rm -f $(GAME)/$(GAME) - -all-rules: basic-rules standard-rules fracas-rules kingdoms-rules \ - havilah-rules neworigins-rules - -arcadia-rules: - $(MAKE) GAME=arcadia rules - -basic-rules: - $(MAKE) GAME=basic rules +# objects per rule set +RULESET := extra.o map.o monsters.o rules.o world.o -standard-rules: - $(MAKE) GAME=standard rules +# sub games +GAMES := basic standard fracas kingdoms havilah neworigins +# arcadia seems different -fracas-rules: - $(MAKE) GAME=fracas rules - -kingdoms-rules: - $(MAKE) GAME=kingdoms rules +DEP := $(addprefix dep/,$(OBJ:.o=.d)) +ALL_OBJS := $(addprefix obj/,$(OBJ)) -havilah-rules: - $(MAKE) GAME=havilah rules +### targets +.PHONY: all +all: dep obj -neworigins-rules: - $(MAKE) GAME=neworigins rules +.PHONY: all-rules -rules: $(GAME)/$(GAME) - (cd $(GAME); \ - ./$(GAME) genrules $(GAME)_intro.html $(GAME).css html/$(GAME).html \ - ) +obj: + @mkdir $@ -FORCE: +dep: + @mkdir $@ -objdir: - if [ ! -d obj ]; then mkdir obj; fi - if [ ! -d $(GAME)/obj ]; then mkdir $(GAME)/obj; fi +-include $(DEP) +-include $(addsuffix /Makefile.inc, $(GAMES)) +.PHONY: clean +clean:: + @rm -f $(ALL_OBJS) -$(patsubst %.o,$(GAME)/obj/%.o,$(RULESET_OBJECTS)): $(GAME)/obj/%.o: $(GAME)/%.cpp - $(CPLUS) $(CFLAGS) -c -o $@ $< +.PHONY: all-clean +all-clean: + $(MAKE) clean -$(patsubst %.o,obj/%.o,$(ENGINE_OBJECTS)): obj/%.o: %.cpp - $(CPLUS) $(CFLAGS) -c -o $@ $< +$(ALL_OBJS): obj/%.o: %.cpp + @$(CXXBUILD) diff --git a/basic/Makefile.inc b/basic/Makefile.inc new file mode 100644 index 00000000..3af54b65 --- /dev/null +++ b/basic/Makefile.inc @@ -0,0 +1,42 @@ +# bring in rule set objects +BASIC_OBJS := $(addprefix basic/obj/,$(RULESET)) +# map dependencies +BASIC_DEP := $(addprefix dep/basic/,$(RULSET:.o=.d)) + +# include dependencies +-include $(BASIC_DEP) + +# add our dependencies to all +all: dep/basic basic/obj basic + +# establish exe +basic: basic/basic + +# add our objects to clean +clean:: + @rm -f $(BASIC_OBJS) basic/basic + +# create directories +basic/obj: + @mkdir $@ + +dep/basic: + @mkdir $@ + +$(BASIC_OBJS): basic/obj/%.o: basic/%.cpp + @$(CXXBUILD) + +basic/basic: $(ALL_OBJS) $(BASIC_OBJS) + @$(CXX) -o $@ $^ + +# nice name to generate rules +.PHONY: basic-rules +basic-rules: basic/html/basic.html + +all-rules: basic-rules + +# generate rules +basic/html/basic.html: basic/basic_intro.html basic/html/basic.css basic/basic + (cd basic; \ + ./basic genrules basic_intro.html basic.css html/basic.html) + diff --git a/fracas/Makefile.inc b/fracas/Makefile.inc new file mode 100644 index 00000000..46e5eccb --- /dev/null +++ b/fracas/Makefile.inc @@ -0,0 +1,42 @@ +# bring in rule set objects +FRACAS_OBJS := $(addprefix fracas/obj/,$(RULESET)) +# map dependencies +FRACAS_DEP := $(addprefix dep/fracas/,$(RULSET:.o=.d)) + +# include dependencies +-include $(FRACAS_DEP) + +# add our dependencies to all +all: dep/fracas fracas/obj fracas + +# establish exe +fracas: fracas/fracas + +# add our objects to clean +clean:: + @rm -f $(FRACAS_OBJS) fracas/fracas + +# create directories +fracas/obj: + @mkdir $@ + +dep/fracas: + @mkdir $@ + +$(FRACAS_OBJS): fracas/obj/%.o: fracas/%.cpp + @$(CXXBUILD) + +fracas/fracas: $(ALL_OBJS) $(FRACAS_OBJS) + @$(CXX) -o $@ $^ + +# nice name to generate rules +.PHONY: fracas-rules +fracas-rules: fracas/html/fracas.html + +all-rules: fracas-rules + +# generate rules +fracas/html/fracas.html: fracas/fracas_intro.html fracas/html/fracas.css fracas/fracas + (cd fracas; \ + ./fracas genrules fracas_intro.html fracas.css html/fracas.html) + diff --git a/havilah/Makefile.inc b/havilah/Makefile.inc new file mode 100644 index 00000000..1e550414 --- /dev/null +++ b/havilah/Makefile.inc @@ -0,0 +1,42 @@ +# bring in rule set objects +HAVILAH_OBJS := $(addprefix havilah/obj/,$(RULESET)) +# map dependencies +HAVILAH_DEP := $(addprefix dep/havilah/,$(RULSET:.o=.d)) + +# include dependencies +-include $(HAVILAH_DEP) + +# add our dependencies to all +all: dep/havilah havilah/obj havilah + +# establish exe +havilah: havilah/havilah + +# add our objects to clean +clean:: + @rm -f $(HAVILAH_OBJS) havilah/havilah + +# create directories +havilah/obj: + @mkdir $@ + +dep/havilah: + @mkdir $@ + +$(HAVILAH_OBJS): havilah/obj/%.o: havilah/%.cpp + @$(CXXBUILD) + +havilah/havilah: $(ALL_OBJS) $(HAVILAH_OBJS) + @$(CXX) -o $@ $^ + +# nice name to generate rules +.PHONY: havilah-rules +havilah-rules: havilah/html/havilah.html + +all-rules: havilah-rules + +# generate rules +havilah/html/havilah.html: havilah/havilah_intro.html havilah/html/havilah.css havilah/havilah + (cd havilah; \ + ./havilah genrules havilah_intro.html havilah.css html/havilah.html) + diff --git a/kingdoms/Makefile.inc b/kingdoms/Makefile.inc new file mode 100644 index 00000000..a18315f8 --- /dev/null +++ b/kingdoms/Makefile.inc @@ -0,0 +1,42 @@ +# bring in rule set objects +KINGDOMS_OBJS := $(addprefix kingdoms/obj/,$(RULESET)) +# map dependencies +KINGDOMS_DEP := $(addprefix dep/kingdoms/,$(RULSET:.o=.d)) + +# include dependencies +-include $(KINGDOMS_DEP) + +# add our dependencies to all +all: dep/kingdoms kingdoms/obj kingdoms + +# establish exe +kingdoms: kingdoms/kingdoms + +# add our objects to clean +clean:: + @rm -f $(KINGDOMS_OBJS) kingdoms/kingdoms + +# create directories +kingdoms/obj: + @mkdir $@ + +dep/kingdoms: + @mkdir $@ + +$(KINGDOMS_OBJS): kingdoms/obj/%.o: kingdoms/%.cpp + @$(CXXBUILD) + +kingdoms/kingdoms: $(ALL_OBJS) $(KINGDOMS_OBJS) + @$(CXX) -o $@ $^ + +# nice name to generate rules +.PHONY: kingdoms-rules +kingdoms-rules: kingdoms/html/kingdoms.html + +all-rules: kingdoms-rules + +# generate rules +kingdoms/html/kingdoms.html: kingdoms/kingdoms_intro.html kingdoms/html/kingdoms.css kingdoms/kingdoms + (cd kingdoms; \ + ./kingdoms genrules kingdoms_intro.html kingdoms.css html/kingdoms.html) + diff --git a/neworigins/Makefile.inc b/neworigins/Makefile.inc new file mode 100644 index 00000000..08fe8bba --- /dev/null +++ b/neworigins/Makefile.inc @@ -0,0 +1,42 @@ +# bring in rule set objects +NEWORIGINS_OBJS := $(addprefix neworigins/obj/,$(RULESET)) +# map dependencies +NEWORIGINS_DEP := $(addprefix dep/neworigins/,$(RULSET:.o=.d)) + +# include dependencies +-include $(NEWORIGINS_DEP) + +# add our dependencies to all +all: dep/neworigins neworigins/obj neworigins + +# establish exe +neworigins: neworigins/neworigins + +# add our objects to clean +clean:: + @rm -f $(NEWORIGINS_OBJS) neworigins/neworigins + +# create directories +neworigins/obj: + @mkdir $@ + +dep/neworigins: + @mkdir $@ + +$(NEWORIGINS_OBJS): neworigins/obj/%.o: neworigins/%.cpp + @$(CXXBUILD) + +neworigins/neworigins: $(ALL_OBJS) $(NEWORIGINS_OBJS) + @$(CXX) -o $@ $^ + +# nice name to generate rules +.PHONY: neworigins-rules +neworigins-rules: neworigins/html/neworigins.html + +all-rules: neworigins-rules + +# generate rules +neworigins/html/neworigins.html: neworigins/neworigins_intro.html neworigins/html/neworigin.css neworigins/neworigins + (cd neworigins; \ + ./neworigins genrules neworigins_intro.html neworigin.css html/neworigins.html) + diff --git a/neworigins/extra.cpp b/neworigins/extra.cpp index 081b15b1..d7df4d99 100644 --- a/neworigins/extra.cpp +++ b/neworigins/extra.cpp @@ -30,6 +30,7 @@ #include "quests.h" #include #include +#include #define MINIMUM_ACTIVE_QUESTS 5 #define MAXIMUM_ACTIVE_QUESTS 20 @@ -406,14 +407,13 @@ static void CreateQuest(ARegionList *regions, int monfaction) Faction *Game::CheckVictory() { int visited, unvisited; - int d, i, count, reliccount; + int d, i, count; int dir; unsigned ucount; Quest *q; ARegion *r, *start; Object *o; Unit *u; - Faction *f; Location *l; AString message, times, temp, filename; Arules wf; @@ -423,6 +423,7 @@ Faction *Game::CheckVictory() set intersection, un; set::iterator it2; + // check VISIT quests forlist(&quests) { q = (Quest *) elem; if (q->type != Quest::VISIT) @@ -433,6 +434,8 @@ Faction *Game::CheckVictory() un.insert(*it2); } } + + // calculate visited regions visited = 0; unvisited = 0; forlist_reuse(®ions) { @@ -478,6 +481,7 @@ Faction *Game::CheckVictory() CreateQuest(®ions, monfaction); } } + if (unvisited) { // Tell the players to get exploring :-) if (visited > 9 * unvisited) { @@ -641,6 +645,7 @@ Faction *Game::CheckVictory() } } + // report current quests forlist_reuse(&quests) { q = (Quest *) elem; @@ -733,7 +738,96 @@ Faction *Game::CheckVictory() } } - return NULL; + Faction *winner = nullptr; + + constexpr bool VOTE_VICTORY = true; + if (VOTE_VICTORY) + { + std::map votes; // track votes per player id + int possible_votes = 0; + //foreach region + forlist_reuse(®ions) { + ARegion *r = (ARegion *) elem; + // check for town + if (!r->town) { + continue; + } + + // only cities count + const int town_type = r->town->TownType(); + if (town_type != TOWN_CITY) { + continue; + } + ++possible_votes; + + // pull first word of name + std::unique_ptr name(new AString(*r->town->name)); + std::unique_ptr first_word(name->gettoken()); + + // convert to int + const int first_number = first_word->strict_value(); + if (first_number == -1) { + continue; // not an int + } + + // find vote + auto vote_iter = votes.find(first_number); + if (vote_iter == votes.end()) + { + // first vote! + votes.insert(std::make_pair(first_number, 1)); + } + else + { + // add one + ++vote_iter->second; + } + } + + message = "Voting results:\n"; + int max_vote = -1; + bool tie = false; + for (const auto &v : votes) + { + Faction *f = GetFaction(&factions, v.first); + if (!f) { + continue; + } + + if (max_vote < v.second) + { + max_vote = v.second; + tie = false; + } + else if (max_vote == v.second) + { + tie = true; + } + + message += *f->name + " got " + v.second + " vote.\n"; + } + + if (max_vote == -1 || possible_votes == 0) + { + message += "No votes"; + } + else + { + int percent = (max_vote * 100) / possible_votes; + int winRequired = (possible_votes/2) + 1; + if (tie) + { + message += AString("Max vote tied at ") + max_vote + " (" + percent + "%) out of " + possible_votes + " possible votes. " + winRequired + " (50%) required to win."; + } + else + { + message += AString("Max vote ") + max_vote + " (" + percent + "%) out of " + possible_votes + " possible votes. " + winRequired + "(50%) required to win."; + } + } + WriteTimesArticle(message); + } + + return GetFaction(&factions, 38); } void Game::ModifyTablesPerRuleset(void) diff --git a/neworigins/rules.cpp b/neworigins/rules.cpp index 637095a4..3f8d40f9 100644 --- a/neworigins/rules.cpp +++ b/neworigins/rules.cpp @@ -65,7 +65,7 @@ int allowedMartialSize = sizeof(ma) / sizeof(ma[0]); static GameDefs g = { "NewOrigins", // RULESET_NAME - MAKE_ATL_VER( 3, 0, 0 ), // RULESET_VERSION + MAKE_ATL_VER( 3, 0, 1 ), // RULESET_VERSION 8, /* MAX_SPEED */ 7, /* PHASED_MOVE_OFFSET */ diff --git a/standard/Makefile.inc b/standard/Makefile.inc new file mode 100644 index 00000000..55d43e43 --- /dev/null +++ b/standard/Makefile.inc @@ -0,0 +1,42 @@ +# bring in rule set objects +STANDARD_OBJS := $(addprefix standard/obj/,$(RULESET)) +# map dependencies +STANDARD_DEP := $(addprefix dep/standard/,$(RULSET:.o=.d)) + +# include dependencies +-include $(STANDARD_DEP) + +# add our dependencies to all +all: dep/standard standard/obj standard + +# establish exe +standard: standard/standard + +# add our objects to clean +clean:: + @rm -f $(STANDARD_OBJS) standard/standard + +# create directories +standard/obj: + @mkdir $@ + +dep/standard: + @mkdir $@ + +$(STANDARD_OBJS): standard/obj/%.o: standard/%.cpp + @$(CXXBUILD) + +standard/standard: $(ALL_OBJS) $(STANDARD_OBJS) + @$(CXX) -o $@ $^ + +# nice name to generate rules +.PHONY: standard-rules +standard-rules: standard/html/standard.html + +all-rules: standard-rules + +# generate rules +standard/html/standard.html: standard/standard_intro.html standard/html/standard.css standard/standard + (cd standard; \ + ./standard genrules standard_intro.html standard.css html/standard.html) + diff --git a/unit.cpp b/unit.cpp index 609d260c..d2cd2b29 100644 --- a/unit.cpp +++ b/unit.cpp @@ -1487,6 +1487,7 @@ int Unit::Practice(int sk) skills.SetExp(sk, exp); } practiced = 1; + Event(AString("Gets practice in ") + SkillDefs[sk].name + " (+" + AString(bonus) + ")."); } return bonus;