#!/bin/nawk -f BEGIN { true = (0 == 0); false = ! true; validList = false; powText[0] = "Master"; powText[1] = "Austria"; powText[2] = "England"; powText[3] = "France"; powText[4] = "Germany"; powText[5] = "Italy"; powText[6] = "Russia"; powText[7] = "Turkey"; maxPow=7; player[0] = false; for (pow=1; pow <= maxPow; pow++) { control[pow] = 0; for (curPow=1; curPow<=maxPow; curPow++) { save_bid[curPow,pow] = 0; bid[curPow,pow] = 0; player[pow] = false; } } # for stalemate = false; CarryOver = true; OverBidding = true; IncomeType = "Rent"; Income = 1; NonMovement = "Ordered"; NonPlayer = "NMR"; VictoryCond = "Intimate" } /^GAME/ { game = $2; } /^JUDGE/ { judge = $2; } /^YEAR/ { year = $2; nextYear = year; } /^SEASON/ { # assumes SEASON follows YEAR in file. season = $2 curDir = season; if (season == "fall") { nextSeason = "thaw"; newDir = "spring"; nextYear = year + 1; } if (season == "thaw") { nextSeason = "spring"; curDir = nextSeason; newDir = nextSeason; } if (season == "spring") { nextSeason = "fall"; newDir = nextSeason; } } /^PASSWORD/ { password[0] = $2; } /^POWER/ { currentPower = powerNumber($2); player[currentPower] = true; password[currentPower] = $3; reserve[currentPower] = $4; } /^CarryOver/ {CarryOver = true; } /^noCarryOver/ {CarryOver = false; } /^OverBidding/ { OverBidding = true; } /^noOverBidding/ { OverBidding = false; } /^IncomeType/ { IncomeType = $2; } /^Income/ { Income = $2; } /^NonMovement/ { NonMovement = $2; } /^NonPlayer/ { NonPlayer = $2; } /^VictoryCond/ { VictoryCond = $2; } /^[Bb][Ii][Dd]/ { curPow = powerNumber($2); mercenary = powerNumber($3); if (! player[curPow]) { print "Bid from non-player ignored: " $0; } else if (player[mercenary]) { print "Bid on player ignored: " $0; } else { save_bid [curPow,mercenary] = $4; bid [curPow,mercenary] = $4; } } /^[Ss][Tt][Aa][Ll][Ee][Mm][Aa][Tt][Ee]/ { stalemate = true; } /^CONTROL/ { control[powerNumber($3)] = powerNumber($2); } /^The following players are signed up for game/ { validList = true; } ((($2 ~ /Army/) || ($2 ~ /Fleet/)) && \ (($0 !~ /can retreat/) && ($0 !~ /No Order Processed/))) { curPow = powerNumber($1); location = $3 if ($4 !~ /No/ && $5 !~ /coast/) { location = location " " $4 } if ($0 ~ "North Atlantic") { location = "NAO" } if ("of" == $4) { location = location " " $5 } gsub(/[ ,.]+$/," ",location); unit[location] = curPow; } # check for supply center report (($3 ~ /Supply/) && ($4 ~ /center/)) { curPow = powerNumber($1); if ("Fixed" == IncomeType) { income[curPow] = Income; } if ("Rent" == IncomeType) { if (0 != curPow) { income[curPow] = Income * $2; } } } # all input processed, do the computations and generate the output END { if (! validList) { abort("No valid list file (did you use a results file instead?)"); } # figure out the output directories etc. masterFile = game "/master.file"; gameFile = game "/" nextYear "/" newDir "/game.file"; commandFile = game "/" year "/" curDir "/commands"; # process the year if (! checkVictory()) { if ("thaw" == season) { PreBidReport() } else { if ("spring" == season) { do { penalty[0] = false; procBids(); } while (penalty[0]); for (curPow=1; curPow <= maxPow; curPow++) { if (! CarryOver) { avail[curPow] = cost[curPow] = 0; } reserve[curPow] = avail[curPow] - cost[curPow]; } } outputCommandfile(); } outputGamefile(); } } #====================================================================== # abort(string): display message and divide by 0 function abort(string) { print string; print 0/0; } #====================================================================== # powName(powNum): returns the text for a give power number function powName(powNum) { if (powNum > maxPow) return ("Switzerland"); return (powText[powNum]); } #====================================================================== # powerNumber (powerName): returns the number of the power corresponding to # the name passed in. function powerNumber (powerName) { alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; upperc = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"; ch = substr(powerName, 1, 1) idx = index(alphabet, ch); if (0 == idx) return (-1); ch = substr(upperc, idx, 1); for (powNum_i=1; powNum_i<=maxPow; powNum_i++) { if (substr(powText[powNum_i], 1, 1) == ch) { return (powNum_i); } } return (0); } #====================================================================== # procBids(): process the bidding for control of mercenaries function procBids() { # zero out costs for (pb_bidder=1; pb_bidder<=maxPow; pb_bidder++) { cost[pb_bidder] = 0; # if overbidding not allowed, check if somebody goofed if (! OverBidding) { total = 0 for (pb_merc = 1; pb_merc <= maxPow; pb_merc++) { total += bid[pb_bidder, pb_merc]; } # for if (total > income[pb_bidder] + reserve[pb_bidder]) { abort("*** OVERBIDDING FORBIDDEN: " powName(pb_bidder) " must re-bid."); } # if } # for } # if # fill out contracts for mercenaries for (pb_merc = 1; pb_merc <= maxPow; pb_merc++) { controler = 0; highBid = 0; for (pb_bidder=1; pb_bidder<=maxPow; pb_bidder++) { curBid = bid[pb_bidder,pb_merc]; if (bid[pb_bidder,pb_merc] > highBid) { highBid = curBid; controler = pb_bidder; } else if (bid[pb_bidder,pb_merc] == highBid) controler = 0; } if (0 != controler) { cost[controler] += bid[controler, pb_merc]; } control[pb_merc] = controler; } # check for penalties for (pb_bidder=1; pb_bidder<=maxPow; pb_bidder++) { if (! player[pb_bidder]) continue; avail[pb_bidder] = reserve[pb_bidder] + income[pb_bidder]; penalty[pb_bidder] = cost[pb_bidder] > avail[pb_bidder]; # if overbid, time to pay up if (penalty[pb_bidder]) { penalty[0] = overbid[pb_bidder] = true; cost[pb_bidder] = income[pb_bidder] = reserve[pb_bidder] = 0; for (pb_merc = 1; pb_merc <= maxPow; pb_merc++) { if (control[pb_merc] == pb_bidder) { control[pb_merc] = 0; bid[pb_bidder,pb_merc] = 0; } } } } # reward opponent(s) of penalized power(s) with a price break if (penalty[0]) { for (pb_bidder=1; pb_bidder<=maxPow; pb_bidder++) { if (! player[pb_bidder]) continue; for (pb_merc = 1; pb_merc <= maxPow; pb_merc++) { if ((! penalty[pb_bidder]) && (0 != bid[pb_bidder,pb_merc])) { bid[pb_bidder,pb_merc] = int ((1 + bid[pb_bidder,pb_merc]) / 2); } } } } } #====================================================================== # outputGamefile(): generates the game and master files for the next season function outputGamefile() { print "GAME " game > masterFile; print "JUDGE " judge > masterFile; print "PASSWORD " password[0] > masterFile; print "YEAR " nextYear > masterFile; print "SEASON " nextSeason > masterFile; for (og_i=1; og_i<=maxPow; og_i++) { if (player[og_i]) { print "POWER " powName(og_i) " " password[og_i] " " reserve[og_i] > gameFile } } if (CarryOver) { print "CarryOver" >masterFile; } else { print "noCarryOver" >masterFile; } if (OverBidding) { print "OverBidding" >masterFile; } else { print "noOverBidding" >masterFile; } print "IncomeType", IncomeType >masterFile; print "Income", Income >masterFile; print "NonMovement", NonMovement >masterFile; print "NonPlayer", NonPlayer >masterFile; print "VictoryCond", VictoryCond >masterFile; if ("spring" == season) { for (og_i=1; og_i<=maxPow; og_i++) { if (0 != control[og_i]) { print "CONTROL " powName(control[og_i]) " " powName(og_i) > gameFile; } } } } #====================================================================== # outputCommandfile(): creates the file of commands to intialize the # next season, especially proxies and holds. # function outputCommandfile() { # build & send mail message on behalf of GM print":" > commandFile; print"cat <commandFile; print "signon m" game " " password[0] >commandFile; # broadcast the bid results: doBroadcast(commandFile); # now issue orders for each non-player unit initialOrders(commandFile); print "signoff" > commandFile; print "eoglobal" > commandFile; setPasswords(commandFile); } #====================================================================== # doBroadcast: function doBroadcast(out) { print "broadcast" > out; print "=====", season, year "=====" > out; print " " >out; if ("spring" == season) { print "*** Bidding Results ***" > out; # Bids. print " ">out; print "--- Player Bids ---" >out; print " A E F G I R T" > out for (db_pow=1; db_pow <= maxPow; db_pow++) { if (player[db_pow]) { line = substr(powName(db_pow),1,1) " "; for (db_mer=1; db_mer <= maxPow; db_mer++) { if (player[db_mer]) { db_tmp = " - "; } else { db_tmp = sprintf ("%2d ", save_bid[db_pow, db_mer]); } line = line db_tmp; } if (overbid[db_pow]) { line = line " * OVERBID *"; } print line >out; } } # financial results if (CarryOver) { print " " >out; print "--- Reserves ---" >out; for (db_i=1; db_i<=maxPow; db_i++) { if (player[db_i]) { db_pow = powName(db_i); print db_pow " " reserve[db_i] > out; } } } } # spring only # Political results print " ">out; print "--- Mercenary Control ---" >out; db_proxy_needed = true; for (db_pow=1; db_pow <= maxPow; db_pow++) { if (! player[db_pow]) { pow = powName(db_pow); controler = control[db_pow]; if (0 != controler) { print pow " controled by " powName(controler) > out; db_proxy_needed = true; } else { print pow " uncontroled" > out; } } } if (db_proxy_needed) { print " " > out print "Proxies for controled mercenaries submitted." > out } print "endpress" > out; } #====================================================================== # initialOrders: for each non-player unit, issues either a hold or a proxy function initialOrders(out) { for (u in unit) { owner = unit[u]; if (! player[owner]) { controler = control[owner]; if (0 == controler) { print u " hold" > out; } else { print u " proxy to " powName(controler) > out; } } } } #====================================================================== # create a here-script for each controled and uncontrolled power to set # the password to either the GM or the controler function setPasswords(out) { print "sleep 10" >out; # give the proxies time to clear for (sp_pow=1; sp_pow <= maxPow; sp_pow++) { if (! player[sp_pow]) { print "cat << eo" powName(sp_pow) " | dipmail " judge, game> out; print "signon m" game " " password[0] >out; print "become " powName(sp_pow) >out; newPassword = password[0]; if ((0 != control[sp_pow]) && ("Ordered" == NonMovement)) { newPassword = password[control[sp_pow]]; } print "set password " newPassword > out; print "signoff" > out; print "eo" powName(sp_pow) > out; print "sleep 2" >out; # give the previous time to clear } } print "#" >out; } #====================================================================== # checkVictory() function checkVictory() { if ("Intimate" != VictoryCond) { return (false); ## let Judge decide } potential = stalemate; for (cv_i=1; cv_i<=maxPow; cv_i++) { vp[cv_i] = 0; } for (loc in unit) { owner = homeOwner(loc); occupier = unit[loc]; if (player[owner] && player[occupier] && (occupier != owner)) { potential = true; if (vp[occupier] < 3) vp[occupier]++; } } if (! potential) return (potential); # highest_vp = 0; winner=0; for (cv_i=1; cv_i<=maxPow; cv_i++) { cur_vp = vp[cv_i] * 100 + reserve[cv_i] + income[cv_i]; if (cur_vp == highest_vp) { winner = 0; } if (cur_vp > highest_vp) { winner = cv_i; next_vp = highest_vp; highest_vp = cur_vp; } } if (0 != winner) { proclaimWinner(winner, highest_vp, next_vp); return (true); } return (false); } #====================================================================== # proclaimWinner: function proclaimWinner(powNum, vpw, vpl) { print "We have a winner!"; print "cat << eog | dipmail " judge, game >commandFile; print "signon m" game " " password[0] > commandFile; print "broadcast" > commandFile; print " " > commandFile; print " * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *" > commandFile; print " " > commandFile; print \ " " powName(powNum) " is the winner, " vpw " victory points to " \ vpl "." > commandFile; print " Congratulations on a game well played!" > commandFile; print " " > commandFile; print " * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *" > commandFile; print "endpress" > commandFile; print "terminate" > commandFile; print "signoff" > commandFile; print "eog" > commandFile; } #====================================================================== # homeOwner: function homeOwner(centerName) { if ((centerName ~ /Trieste/) || (centerName ~ /Vienna/) || (centerName ~ /Budapest/)) return (powerNumber("Austria")); if ((centerName ~ /London/) || (centerName ~ /Edinburg/) || (centerName ~ /Liverpool/)) return (powerNumber("England")); if ((Army centerName ~ /Paris/) || (centerName ~ /Marseilles/) || (centerName ~ /Brest/)) return (powerNumber("France")); if ((centerName ~ /Berlin/) || (centerName ~ /Kiel/) || (centerName ~ /Munich/)) return (powerNumber("Germany")); if ((centerName ~ /Venice/) || (centerName ~ /Rome/) || (centerName ~ /Naples/)) return (powerNumber("Italy")); if ((centerName ~ /Moscow/) || (centerName ~ /Sevastopol/) || (centerName ~ /St Petersburg/) || (centerName ~ /Warsaw/)) \ return (powerNumber("Russia")); if ((centerName ~ /Constantinople/) || (centerName ~ /Ankara/) || (centerName ~ /Smyrna/)) return (powerNumber("Turkey")); # not a home center for a power: assign to gm. return (0); } #---------------------------------------------------------------------- # PreBidReport: display income and reserve for the players. function PreBidReport() { print "cat << eog | dipmail " judge, game >commandFile; print "signon m" game " " password[0] > commandFile; print "list" >commandFile; # get list to use as game.file for bid adjudication. print "broadcast" > commandFile; print " " > commandFile; print "*** Available credit for bids, " season " " year " ***" > commandFile; print " reserve income total" >commandFile; for (pbr_pow = 1; pbr_pow <= maxPow; pbr_pow++) { if (player[pbr_pow]) { printf ("%c %2d %2d %2d\n", substr(powName(pbr_pow),1,1), reserve[pbr_pow], income[pbr_pow], reserve[pbr_pow] + income[pbr_pow]) >commandFile; } } print " " > commandFile; print "Please submit your bids via 'press to m'" > commandFile; print "eog" > commandFile; }