Skip to content

Instantly share code, notes, and snippets.

@nulldatamap
Created May 17, 2014 00:45
Show Gist options
  • Select an option

  • Save nulldatamap/c8bf55e8189c1b7ce1b3 to your computer and use it in GitHub Desktop.

Select an option

Save nulldatamap/c8bf55e8189c1b7ce1b3 to your computer and use it in GitHub Desktop.
// game.rs
extern crate rand;
use self::rand::Rng;
use std::io;
// Used for easily modifiable rules
pub struct GameRules {
// Deck rules
maxDeckSize : int,
minDeckSize : int,
maxCardDuplicates: int,
maxMinionCount : int,
maxBaseCount : int,
minMinionCount : int,
minBaseCount : int,
maxEventCount : int,
minEventCount : int,
maxActionCount : int,
minActionCount : int,
maxStructureCount: int,
minStructureCount: int,
// Game rules
startingBases : int,
startingDraw : int,
mulliganCount : int,
startingResouces : int,
resourceGain : int,
cardGain : int,
maxHandSize : int,
playfieldSize : int,
baseSlotCount : int,
maxMinionHealth : int,
maxMinionAttack : int,
}
pub static defaultRules : GameRules = GameRules {
maxDeckSize : 30,
minDeckSize : 30,
maxCardDuplicates: 2,
maxMinionCount : 30,
minMinionCount : 0,
maxBaseCount : 5,
minBaseCount : 0,
maxEventCount : 30,
minEventCount : 0,
maxActionCount : 30,
minActionCount : 0,
maxStructureCount: 30,
minStructureCount: 0,
// Game rules
startingBases : 1,
startingDraw : 3,
mulliganCount : 1,
startingResouces : 1,
resourceGain : 1,
cardGain : 2,
maxHandSize : 10,
playfieldSize : 9,
baseSlotCount : 3,
maxMinionHealth : 100,
maxMinionAttack : 100,
};
pub struct Game<'a> {
rules : GameRules,
friendly : Player,
opponent : Player,
state : State,
board : Board<'a>
}
impl<'a> Game<'a> {
pub fn new<'a>( r : GameRules, fd : Vec<Card>, od : Vec<Card> ) -> Option<Game<'a>> {
if validateDeck( &od, r ) && validateDeck( &fd, r ) {
return Some( Game{ rules: r
, friendly: Player::new( fd )
, opponent: Player::new( od )
, state : State::initalState()
, board : Board::empty() } );
}else {
return None;
}
}
/*
Game order:
= Game join
! Both join with a valid deck.
! A random base is drawn and played for each player.
! Each player draw 3 cards
Each is allowed to mulligan each of the drawn cards once.
= Player turn
Draw a card.
% Turn start
Trigger turn start event
% Turn Action {
Let player play any card they can afford, and sacrifice once.
Trigger turn action events
% Turn Action }
% End turn
Trigger turn end event
Opponents turn.
*/
pub fn startGame<'a>( &mut self ) {
self.friendly.shuffleDeck();
self.opponent.shuffleDeck();
self.friendly.drawAnyCards( self.rules.startingDraw );
self.opponent.drawAnyCards( self.rules.startingDraw );
let fhand = self.getMulliganInput();
self.friendly.mulligan( fhand );
let ohand = self.getMulliganInput();
self.opponent.mulligan( ohand );
}
pub fn getMulliganInput( &self ) -> Vec<bool> {
let mut lne;
println!( "Cards to mulligan: " );
loop {
match io::stdin().read_line() {
Ok( _inp ) => lne = _inp,
Err( err ) => fail!( "Fail to get mulligan: {}", err.desc )
}
}
}
}
pub enum Turn {
FriendlyTurn,
OpponentTurn
}
pub enum Phase {
StartingPhase,
MidPhase,
EndingPhase
}
pub struct State {
turn : Turn,
phase : Phase
}
impl State {
pub fn initalState() -> State {
State{ turn: FriendlyTurn, phase: StartingPhase }
}
}
pub struct Player {
deck : Vec<Card>,
hand : Vec<Card>,
graviyard : Vec<Card>,
resources : int
}
impl Player {
pub fn new( deck : Vec<Card> ) -> Player {
return Player{ deck: deck
, hand: Vec::new()
, graviyard: Vec::new()
, resources: 0 };
}
pub fn shuffleDeck( &mut self ) {
let size = self.deck.len();
let mut ndeck = Vec::with_capacity( size );
let mut rng = rand::task_rng();
loop {
let ds = self.deck.len();
match self.deck.swap_remove( rng.gen::<uint>() % ds ) {
Some( card ) => ndeck.push( card ),
None => break
}
}
self.deck = ndeck;
}
pub fn drawAnyCards( &mut self, amount : int ) {
for _ in range::<int>( 0, amount ) {
match self.deck.pop() {
Some( card ) => self.hand.push( card ),
None => break
}
}
}
pub fn mulligan( &mut self, keeps : Vec<bool> ) {
if self.hand.len() != keeps.len() {
fail!( "Mismatched hand and mulligan vectors." );
}
let mut nhand = Vec::new();
for i in range( 0, keeps.len() ) {
let card = *self.hand.get( i );
if !keeps.get( i ) {
self.deck.push( card );
}else {
nhand.push( card );
}
}
let missing = keeps.len() - nhand.len();
self.hand = nhand;
if missing > 0 {
self.drawAnyCards( missing as int );
}
}
}
pub struct BoardHalf<'a> {
playfield : Vec<Minion<'a>>,
events : Vec< |&'a mut Base<'a>, &'a mut Game<'a>| : 'a -> bool > ,
bases : Vec<Base<'a>>
}
impl<'a> BoardHalf<'a> {
pub fn empty<'a>() -> BoardHalf<'a> {
BoardHalf{ playfield: Vec::new(), events: Vec::new(), bases: Vec::new() }
}
}
pub struct Board<'a> {
frieldyHalf : BoardHalf<'a>,
opponentHalf : BoardHalf<'a>
}
impl<'a> Board<'a> {
pub fn empty<'a>() -> Board<'a> {
Board{ frieldyHalf: BoardHalf::empty(), opponentHalf: BoardHalf::empty() }
}
}
pub struct Minion<'a> {
health : int,
maxHealth : int,
attack : int,
card : MinionCard<'a>
}
pub struct Base<'a> {
health : int,
maxSlotCount : int,
slots : Vec<Structure<'a>>,
card : &'a BaseCard<'a>
}
pub struct Structure<'a> {
health : int,
maxHealth : int,
attack : int,
card : &'a StructureCard<'a>
}
pub enum CardKind<'a> {
MinionKind( MinionCard<'a> ),
BaseKind( BaseCard<'a> ),
EventKind( EventCard<'a> ),
ActionKind( ActionCard<'a> ),
StructureKind( StructureCard<'a> )
}
struct MinionCard<'a> {
health : int,
attack : int,
behaviour : Vec< |&'a mut Minion<'a>, &'a mut Game<'a>| : 'a >
}
struct BaseCard<'a> {
health : int,
slotCount : int,
behaviour : Vec< |&'a mut Base<'a>, &'a mut Game<'a>| : 'a >
}
type EventCard<'a> = |&'a mut Game<'a>| : 'a;
type ActionCard<'a> = |&'a mut Game<'a>| : 'a -> bool;
struct StructureCard<'a> {
health : int,
attack : int,
behaviour : Vec< |&'a mut Structure, &'a mut Game| : 'a >
}
pub struct CardDestriptor<'a> {
cost : int,
name : ~str,
text : ~str,
flavor : ~str,
kind : CardKind<'a>
}
// Card is just a reference to a CardDestriptor
// and the cost ( since that can change )
pub struct Card {
cost : int,
descriptor : &'static CardDestriptor<'static>
}
pub fn validateDeck( deck : &Vec<Card>, rules : GameRules ) -> bool {
let mut acc = deck.len() as int <= rules.maxDeckSize;
acc &= deck.len() as int >= rules.minDeckSize;
return acc;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment