forum.webdiplomacy.net

webDip dev coordination forum / public access todo list
It is currently Mon Sep 25, 2017 12:47 am

All times are UTC




Post new topic Reply to topic  [ 13 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Sun May 23, 2010 7:50 am 
Offline

Joined: Wed Jul 29, 2009 10:22 am
Posts: 841
Now that more and more people start working on variants I think it might be useful to make a collection of all the small changes the different variants do so anybody that needs a special rule-change can take a look if there is working code already.

Over the next few days I'll add examples on how to do changes here in this thread.

Oliver


Top
 Profile  
 
PostPosted: Sun May 23, 2010 7:59 am 
Offline

Joined: Wed Jul 29, 2009 10:22 am
Posts: 841
Custom start:

adjucatorPreGame: You need to make generate an empty array for the country units and disable the initial creation of the starting units and occupation of the starting territories:
Code:
<?php

class CustomStartVariant_adjudicatorPreGame extends ClassicVariant_adjudicatorPreGame {

   protected $countryUnits = array(
      'England' => array(),
      'France' => array(),
      'Italy' => array(),
      'Germany' => array(),
      'Austria' => array(),
      'Turkey' => array(),
      'Russia' => array()
      );

   // Disabled; no initial units or occupations
   protected function assignUnits() { }

   protected function assignUnitOccupations() { }

}


processOrdersBuilds:
If we are in the 1st turn during the generation of the orders for the first turn we need to populate the "Orders" in the database for all the players. You can make "Empty" build orders, but I prefer to make some default orders in case someone misses the first turn, so the game is not ruined.
Code:
<?php

class CustomStartVariant_processOrderBuilds extends processOrderBuilds {

   protected $countryUnits = array(
      'England'=> array('London' =>'Fleet','Liverpool'=>'Army','Edinburgh'     =>'Fleet'),
      'France' => array('Brest'  =>'Fleet','Paris'    =>'Army','Marseilles'    =>'Army' ),
      'Italy'  => array('Naples' =>'Fleet','Venice'   =>'Army','Rome'          =>'Army' ),
      'Germany'=> array('Kiel'   =>'Fleet','Berlin'   =>'Army','Munich'        =>'Army' ),
      'Austria'=> array('Trieste'=>'Fleet','Vienna'   =>'Army','Budapest'      =>'Army' ),
      'Turkey' => array('Ankara' =>'Fleet','Smyrna'   =>'Army','Constantinople'=>'Army' ),
      'Russia' => array('Moscow' =>'Army' ,'Warsaw'   =>'Army','Sevastopol'    =>'Fleet' ,
                    'St. Petersburg (South Coast)'=>'Fleet')
      );

   public function create()
   {
      global $DB, $Game;
      if ($Game->turn == 0) {

         $terrIDByName = array();
         $tabl = $DB->sql_tabl("SELECT id, name FROM wD_Territories WHERE mapID=".$Game->Variant->mapID);
         while(list($id, $name) = $DB->tabl_row($tabl))
            $terrIDByName[$name]=$id;

         $UnitINSERTs = array();
         foreach($this->countryUnits as $countryName => $params)
         {
            $countryID = $Game->Variant->countryID($countryName);

            foreach($params as $terrName=>$unitType)
            {
               $terrID = $terrIDByName[$terrName];
               $unitType = "Build " . $unitType;
               $UnitINSERTs[] = "(".$Game->id.", ".$countryID.", '".$terrID."', '".$unitType."')"; // ( gameID, countryID, terrID, type )
            }
         }
         $DB->sql_put(
            "INSERT INTO wD_Orders ( gameID, countryID, toTerrID, type )
            VALUES ".implode(', ', $UnitINSERTs)
         );      
      } else {
         parent::create();
      }
      
   }
}


ProcessGame.php:
We have to insert a Build-phase right before the first diplomacy phase:
Code:
<?php

class CustomStartVariant_processGame extends processGame {
   public function __construct($id)
   {
      parent::__construct($id);
   }

   protected function changePhase() {
      if( $this->phase == 'Pre-game' )
      {
         // Builds first after the game starts
         $this->setPhase('Builds');

         // This gives the map some color to start with
         $this->archiveTerrStatus();

         return false;
      }
      elseif( $this->phase == 'Builds' && $this->turn==0 )
      {
         // The first Spring builds just finished, make sure we don't go to the next turn

         $this->phase='Pre-game'; // This prevents a turn being added on in setPhase, keeping it in Spring, 1901
         // (It won't activate twice because the next time it won't go into a Builds phase in Spring)

         $this->setPhase('Diplomacy'); // Diplomacy, Spring 1901, and from then on like nothing was different

         $this->archiveTerrStatus();
         return false;
      }
      else
         return parent::changePhase(); // Except those two phases above behave normally
   }
}


Top
 Profile  
 
PostPosted: Sun May 23, 2010 8:02 am 
Offline

Joined: Wed Jul 29, 2009 10:22 am
Posts: 841
If you have a very crowded map you might want to draw the flag right behind the units, not above:
Code:
class Modern2Variant_drawMap extends drawMap {

   // Draw the flags behind the units for a better readability
   public function countryFlag($terrName, $countryID)
   {
      $flagBlackback = $this->color(array(0, 0, 0));

      $flagColor = $this->color($this->countryColors[$countryID]);

      list($x, $y) = $this->territoryPositions[$terrName];

      $coordinates = array(
         'top-left' => array(
                     'x'=>$x-intval($this->fleet['width']/2+2)+1,
                     'y'=>$y-intval($this->fleet['height']/2+2)+1
                     ),
         'bottom-right' => array(
                     'x'=>$x+intval($this->fleet['width']/2+2)-1,
                     'y'=>$y+intval($this->fleet['height']/2+2)-1
                     )
         );

      imagefilledrectangle($this->map['image'],
         $coordinates['top-left']['x'], $coordinates['top-left']['y'],
         $coordinates['bottom-right']['x'], $coordinates['bottom-right']['y'],
         $flagBlackback);
      imagefilledrectangle($this->map['image'],
         $coordinates['top-left']['x']+1, $coordinates['top-left']['y']+1,
         $coordinates['bottom-right']['x']-1, $coordinates['bottom-right']['y']-1,
         $flagColor);
   }

}

?>


Top
 Profile  
 
PostPosted: Sun May 23, 2010 8:11 am 
Offline

Joined: Wed Jul 29, 2009 10:22 am
Posts: 841
Build anywhere:
This one is a bit tricky.
You have to change the javascript-code for the players, so they can select "non-home" sc's too in their browsers.
1st the New javascript code, that loads all "free" SC's of a user, I usually save this to "Resources/supplycenterscorrect.js":
Code:
function SupplyCentersCorrect() {
   SupplyCenters = new Array();
   
   /*
    * In javascript/board/load.js SupplyCenters is created using similar code but only with home SCs,
    * replacing it here allows them to be selected. A modified OrderInterface calls this shortly after load.js.
    */
   Territories.each(function(p){
      var t=p[1];
      if( t.coastParent.supply && t.coastParent.ownerCountryID == context.countryID && Object.isUndefined(t.coastParent.Unit) )
      {
         SupplyCenters.push(t);
      }
   },this);
}

And here you insert the code to the users HTML-page:
Code:
<?php
class PureVariant_OrderInterface extends OrderInterface {

   /**
    * Call the parent constructor transparently to keep things working
    */
   public function __construct($gameID, $variantID, $userID, $memberID, $turn, $phase, $countryID,
      setMemberOrderStatus $orderStatus, $tokenExpireTime, $maxOrderID=false)
   {
      parent::__construct($gameID, $variantID, $userID, $memberID, $turn, $phase, $countryID,
         $orderStatus, $tokenExpireTime, $maxOrderID);
   }

   protected function jsLoadBoard() {
      parent::jsLoadBoard();

      if( $this->phase=='Builds' )
      {
         // Expand the allowed SupplyCenters array to include non-home SCs.
         libHTML::$footerIncludes[] = '../variants/Pure/resources/supplycenterscorrect.js';
         foreach(libHTML::$footerScript as $index=>$script)
            if(strpos($script, 'loadBoard();') )
               libHTML::$footerScript[$index]=str_replace('loadBoard();','loadBoard();SupplyCentersCorrect();', $script);
      }
   }

}
?>


Now you need to change the code that validates the orders:
Code:
<?php

class PureVariant_userOrderBuilds extends userOrderBuilds
{
   public function __construct($orderID, $gameID, $countryID)
   {
      parent::__construct($orderID, $gameID, $countryID);
   }

   protected function toTerrIDCheck()
   {
      global $DB;

      // Don't duplicate destroy validation code
      if( $this->type != 'Build Army' && $this->type != 'Build Fleet' )
         return parent::toTerrIDCheck();

      if( $this->type == 'Build Army' )
      {
         /*
          * Creating an army at which territory
          *
          * Unoccupied supply centers owned by our country, which the specified unit type
          * can be built in. If a parent coast is found return Child entries.
          */
         return $this->sqlCheck("SELECT t.id
            FROM wD_TerrStatus ts
            INNER JOIN wD_Territories t
               ON ( t.id = ts.terrID )
            WHERE ts.gameID = ".$this->gameID."
               AND t.mapID=".MAPID."
               AND ts.countryID = ".$this->countryID."
               AND ts.occupyingUnitID IS NULL
               AND t.id=".$this->toTerrID."
               AND t.supply = 'Yes' AND NOT t.type='Sea'
               AND NOT t.coast = 'Child'");
      }
      elseif( $this->type == 'Build Fleet' )
      {
         return $this->sqlCheck("SELECT IF(t.coast='Parent', coast.id, t.id) as terrID
            FROM wD_TerrStatus ts
            INNER JOIN wD_Territories t ON ( t.id = ts.terrID )
            LEFT JOIN wD_Territories coast ON ( coast.mapID=".MAPID." AND coast.coastParentID = t.id AND NOT t.id = coast.id )
            WHERE ts.gameID = ".$this->gameID."
               AND t.mapID=".MAPID."
               AND ts.countryID = ".$this->countryID."
               AND ts.occupyingUnitID IS NULL
               AND t.supply = 'Yes'
               AND t.type = 'Coast'
               AND (
                  (t.coast='Parent' AND coast.id=".$this->toTerrID.")
                  OR t.id=".$this->toTerrID."
               )
               AND (
                  t.coast='No' OR ( t.coast='Parent' AND NOT coast.id IS NULL )
               )");
      }
   }
}

?>

And finally you have to change the funtion that creates the build-orders so it count all SC's.
Code:
<?php
class PureVariant_processOrderBuilds extends processOrderBuilds
{

   public function create()
   {
      global $DB, $Game;

      $newOrders = array();
      foreach($Game->Members->ByID as $Member )
      {
         $difference = 0;
         if ( $Member->unitNo > $Member->supplyCenterNo )
         {
            $difference = $Member->unitNo - $Member->supplyCenterNo;
            $type = 'Destroy';
         }
         elseif ( $Member->unitNo < $Member->supplyCenterNo )
         {
            $difference = $Member->supplyCenterNo - $Member->unitNo;
            $type = 'Build Army';
         }

         for( $i=0; $i < $difference; ++$i )
         {
            $newOrders[] = "(".$Game->id.", ".$Member->countryID.", '".$type."')";
         }
      }

      if ( count($newOrders) )
      {
         $DB->sql_put("INSERT INTO wD_Orders
                     (gameID, countryID, type)
                     VALUES ".implode(', ', $newOrders));
      }
   }

}

?>


Top
 Profile  
 
PostPosted: Sun May 23, 2010 3:45 pm 
Offline
Site Admin

Joined: Sat Jun 28, 2008 6:24 am
Posts: 892
Good examples, I stickied this. See also the few disabled by default variants which come with the default distribution


Top
 Profile  
 
PostPosted: Sun May 23, 2010 3:52 pm 
Offline

Joined: Wed Oct 08, 2008 12:47 pm
Posts: 726
Indeed.
I was wondering if its worth changing parts of the variant scheme to make things rather neater?
Many of these modifications are common to a number of variants, and so really the inheritance hierarchy should be changed to build off onanother, rather than always defining a new class with most of the same code.


Top
 Profile  
 
PostPosted: Sun May 23, 2010 6:19 pm 
Offline

Joined: Wed Jul 29, 2009 10:22 am
Posts: 841
Change to chatbox. Write a color-codet country-name in front of the text and make the text black.
Useful for variants with many players:
Code:
class ChaosVariant_Chatbox extends Chatbox {

   public function renderMessages($msgCountryID, $messages) {
      global $Member;

      for($i=0; $i<count($messages); $i++)
         if( $messages[$i]['fromCountryID']!=0)
            if (!isset($Member) || $Member->countryID != $messages[$i]['fromCountryID'])
               $messages[$i]['message'] = '[<strong>'.$this->countryName($messages[$i]['fromCountryID']).'</strong>]<span style="color: black;">:'.$messages[$i]['message'];
            else
               $messages[$i]['message'] = '[<strong>You</strong>]<span style="color: black;">:'.$messages[$i]['message'];            

      return parent::renderMessages($msgCountryID, $messages);
   }

}


Top
 Profile  
 
PostPosted: Mon May 24, 2010 7:09 am 
Offline
Site Admin

Joined: Sat Jun 28, 2008 6:24 am
Posts: 892
figlesquidge wrote:
Indeed.
I was wondering if its worth changing parts of the variant scheme to make things rather neater?
Many of these modifications are common to a number of variants, and so really the inheritance hierarchy should be changed to build off onanother, rather than always defining a new class with most of the same code.

Variants can extend variants, it's up to the variant maker whether to reuse a preexisting variant. Not sure if you mean the variant scheme as in the way they work or as in these examples in particular

But I have to admit seeing the expressiveness of the code above, the scope&range&granularity/independence of the hooks available, I'm really pleased with how well it turned out and impressed by how effectively variant creators have exploited it :mrgreen: Though there's always room for improvement


Top
 Profile  
 
PostPosted: Mon May 24, 2010 8:41 am 
Offline

Joined: Wed Jul 29, 2009 10:22 am
Posts: 841
Custom Icons on your map:

First you need to change the path in drawmap.php-resorces to point to your new graphics:
Code:
class SailHo2Variant_drawMap extends drawMap {

   protected function resources() {
      if( $this->smallmap )
      {
         return array(
            'map'     =>'variants/SailHo2/resources/smallmap.png',
            'army'    =>'variants/SailHo2/resources/smallarmy.png',
            'fleet'   =>'variants/SailHo2/resources/smallfleet.png',
            'names'   =>'variants/SailHo2/resources/smallmapNames.png',
            'standoff'=>'images/icons/cross.png'
         );
      }
      else
      {
         return array(
            'map'     =>'variants/SailHo2/resources/map.png',
            'army'    =>'variants/SailHo2/resources/army.png',
            'fleet'   =>'variants/SailHo2/resources/fleet.png',
            'names'   =>'variants/SailHo2/resources/mapNames.png',
            'standoff'=>'images/icons/cross.png'
         );
      }
   }

}


If you want to show the icons in your Orderinterface too you need to change the javascript-code. Save the following code in your resources-directory as iconcorrect.js
Code:
function IconsCorrect() {
   MyOrders.map(function(OrderObj) {
         OrderObj.setUnitIconArea = function(newIcon) {
            if( newIcon == this.currentUnitIcon ) return;
      
            if( this.currentUnitIcon != false )
               $('orderID'+this.id).removeClassName(this.currentUnitIcon.toLowerCase());
      
            $('orderID'+this.id).addClassName(newIcon.toLowerCase());
            this.currentUnitIcon=newIcon;
      
            this.unitIconArea.update('<img src="variants/SailHo2/resources/'+newIcon.toLowerCase()+'.png" alt="'+newIcon+'" />');
         };
      });         
}


And finally load the javascript-patch in the orderinterface:
Code:

class SailHo2Variant_OrderInterface extends OrderInterface {

   public function __construct($gameID, $variantID, $userID, $memberID, $turn, $phase, $countryID,
      setMemberOrderStatus $orderStatus, $tokenExpireTime, $maxOrderID=false)
   {
      parent::__construct($gameID, $variantID, $userID, $memberID, $turn, $phase, $countryID,
         $orderStatus, $tokenExpireTime, $maxOrderID);
   }

   protected function jsLoadBoard() {
      parent::jsLoadBoard();
   
      // Unit-Icons in javascript-code
      libHTML::$footerIncludes[] = '../variants/SailHo2/resources/iconscorrect.js';
      foreach(libHTML::$footerScript as $index=>$script)
         if(strpos($script, 'loadOrdersModel();') )
            libHTML::$footerScript[$index]=str_replace('loadOrdersModel();','loadOrdersModel();IconsCorrect();', $script);
   }
}


Top
 Profile  
 
PostPosted: Thu May 27, 2010 10:17 am 
Offline

Joined: Wed Jul 29, 2009 10:22 am
Posts: 841
Set a fixed bet (eg. 1). Useful for variant-testing and needed for the 2-player maps to prevent abuse.
Code:
class FranceVsAustriaVariant_processMember extends processMember {

   function makeBet($bet)
   {
      parent::makeBet(1);
   }

}


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 13 posts ]  Go to page 1, 2  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB® Forum Software © phpBB Group