mirror of
https://github.com/wassname/cardsforscience.git
synced 2026-06-27 18:58:47 +08:00
292 lines
9.7 KiB
JavaScript
292 lines
9.7 KiB
JavaScript
/**
|
|
* Game object load/saves game resources and stores game objects
|
|
*/
|
|
import ObjectStorage from 'js/storage.js';
|
|
import * as Helpers from './helpers'
|
|
import GameObjects from './gameobjects';
|
|
import * as Rules from './rules.js';
|
|
import cards from 'json/cards.json';
|
|
import achievements from 'json/achievements.json';
|
|
import ruleSimulations from 'json/simulations.json';
|
|
|
|
var Game = (function (Helpers, GameObjects, ObjectStorage,Rules,cards,achievements) {
|
|
'use strict';
|
|
|
|
var Game = function () {
|
|
this.lab = null;
|
|
this.cards = null;
|
|
this.workers = null;
|
|
this.upgrades = null;
|
|
this.achievements = null;
|
|
this.allObjects = {
|
|
// lab: this.lab
|
|
};
|
|
this.loaded = false;
|
|
|
|
this.hypotheses = [];
|
|
this.lastCards= [];
|
|
this.hints=[];
|
|
this.ruleInfo=[];
|
|
this.incorrectCards= [];
|
|
this.rule=undefined;
|
|
this.rules=Rules.rules;
|
|
this.Rule=Rules.Rule;
|
|
};
|
|
|
|
Game.prototype.load = function ($http, $q) {
|
|
var self = this;
|
|
if (this.loaded) {
|
|
return;
|
|
}
|
|
|
|
this.cards = cards; //Helpers.loadFile('json/cards.json');
|
|
this.achievements = require("json/achievements.json"); //Helpers.loadFile('./json/achievements.json');
|
|
|
|
// Turn JSON files into actual game objects and fill map of all objects
|
|
var makeGameObject = function (type, object) {
|
|
// It's okay to define this function here since load is only called
|
|
// once anyway...
|
|
var o = new type(object);
|
|
self.allObjects[o.key] = o;
|
|
return o;
|
|
};
|
|
self.cards = self.cards.map(
|
|
function (r) {
|
|
return makeGameObject(GameObjects.Card, r);
|
|
});
|
|
self.achievements = self.achievements.map(
|
|
function (a) {
|
|
return makeGameObject(GameObjects.Achievement, a);
|
|
});
|
|
|
|
|
|
// put cards in extended array with utility methods
|
|
self.Card = new GameObjects.Cards();
|
|
self.Card.push.apply(self.Card, self.cards);
|
|
self.cards = self.Card;
|
|
|
|
// add rules to load and save states
|
|
self.rules.map(function(o){
|
|
self.allObjects[o.key] = o;
|
|
});
|
|
|
|
// TODO save and load lastCards and incorrectCards
|
|
|
|
// Load states from local store
|
|
for (var key in self.allObjects) {
|
|
var o = self.allObjects[key];
|
|
o.loadState(ObjectStorage.load(key));
|
|
}
|
|
|
|
self.loaded = true;
|
|
return self;
|
|
};
|
|
|
|
Game.prototype.reset = function () {
|
|
// setup game
|
|
this.rule = this.newRule();
|
|
|
|
this.dealHand();
|
|
|
|
// deal new initial cards that follow the rule
|
|
function getInitialCards(rule,cards){
|
|
function _getInitialCards(rule,cards){
|
|
var lastCards = [angular.copy(_.sample(cards))]
|
|
var error,i;
|
|
for (i = 0; i < 52; i++) {
|
|
if (lastCards.length>2) break; // stop here
|
|
var card = angular.copy(_.sample(cards));
|
|
var res;
|
|
try{
|
|
res = rule.test(card,lastCards,cards);
|
|
} catch(e){
|
|
error=e;
|
|
// in case of an error just add a random card
|
|
// this is probobly because it is looking back 2 or 3 cards
|
|
// yet we only have 1
|
|
if (e instanceof TypeError && e.message.endsWith("of undefined"))
|
|
lastCards.push(card);
|
|
else
|
|
throw e
|
|
}
|
|
if (res) lastCards.push(angular.copy(card));
|
|
}
|
|
if (lastCards.length<3) {
|
|
console.warn(
|
|
'Could not deal cards for rule after:',
|
|
i,
|
|
rule.key,
|
|
rule.options,
|
|
rule.describe(),
|
|
_.map(lastCards,'key'),
|
|
error?error.message:''
|
|
);
|
|
// feck, just deal 3 random then
|
|
return null
|
|
|
|
} else {
|
|
return lastCards
|
|
}
|
|
}
|
|
for (var i = 0; i < 100; i++) {
|
|
var initialCards = _getInitialCards(rule,cards)
|
|
if (initialCards) break
|
|
}
|
|
if (!initialCards) {
|
|
throw new Error('Could not deal cards for rule after:' +' ' +
|
|
i +' ' +
|
|
this.rule.key +' ' +
|
|
this.rule.options +' ' +
|
|
this.rule.describe() +' ' +
|
|
_.map(this.lastCards,'key') +' ' +
|
|
error?error.message:'')
|
|
}
|
|
return initialCards
|
|
}
|
|
|
|
let initialCards = getInitialCards(this.rule,this.cards)
|
|
this.lastCards.splice(0,this.lastCards.length);
|
|
this.lastCards.push.apply(this.lastCards,initialCards);
|
|
|
|
this.ruleInfo.splice(0,this.ruleInfo.length);
|
|
this.hints.splice(0,this.hints.length);
|
|
|
|
// empty incorrect cards
|
|
this.incorrectCards.splice(0,this.incorrectCards.length);
|
|
this.incorrectCards.push([]);
|
|
this.incorrectCards.push([]);
|
|
this.incorrectCards.push([]);
|
|
|
|
// reset score
|
|
this.lab.state.score = 200;
|
|
|
|
// new set of hypothes
|
|
this.hypotheses=this.genHypotheses();
|
|
|
|
return this;
|
|
};
|
|
|
|
Game.prototype.genHypotheses = function () {
|
|
// get some hypotheses
|
|
var hypo=[];
|
|
|
|
// a random 2, 2 variations of each
|
|
for (var i = 0; i < 1; i++) {
|
|
var rule = _.sample(this.rules);
|
|
rule = angular.copy(rule);
|
|
rule.randomize();
|
|
hypo.push(rule);
|
|
rule = angular.copy(rule);
|
|
rule.randomize();
|
|
hypo.push(rule);
|
|
}
|
|
|
|
// add the real rule
|
|
var rule = angular.copy(this.rule);
|
|
hypo.push(rule);
|
|
|
|
// and a variation of the real rule
|
|
var rule = angular.copy(this.rule);
|
|
rule.randomize();
|
|
hypo.push(rule);
|
|
|
|
// clean and remember
|
|
hypo = _.uniq(hypo);
|
|
hypo = _.shuffle(hypo);
|
|
|
|
// empty old ones
|
|
this.hypotheses.splice(0,this.hypotheses.length);
|
|
// put in new ones
|
|
for (var i = 0; i < hypo.length; i++) {
|
|
this.hypotheses.push(hypo[i]);
|
|
}
|
|
return this.hypotheses;
|
|
};
|
|
|
|
Game.prototype.newRule = function () {
|
|
// FIXME
|
|
var okRules = _.filter(ruleSimulations,function(s){
|
|
return s.ratioRight>0.1&&s.ratioRight<0.6;
|
|
});
|
|
// var okRules = this.rules;
|
|
// _.map(this.rules,function(r){return r.randomize();});
|
|
// choose and ok rule
|
|
var ruleConfig = _.sample(okRules);
|
|
// now find the rule and set these options
|
|
var rule = _.find(this.rules,{key:ruleConfig.key});
|
|
var options = ruleConfig.options;
|
|
if (typeof options==="string") options = JSON.parse(options);
|
|
rule.setOptions(options);
|
|
return this.rule = rule;
|
|
};
|
|
|
|
Game.prototype.dealHand = function (n) {
|
|
n=n||12;
|
|
|
|
var sample=_.sampleSize(this.cards,n);
|
|
|
|
// empty all cards
|
|
this.cards.map(function(card){
|
|
card.state.amount=0;
|
|
});
|
|
// now increase the value of our sample
|
|
for (var i = 0; i < sample.length; i++) {
|
|
var card = sample[i];
|
|
this.cards.get(card.key).state.amount++;
|
|
}
|
|
};
|
|
Game.prototype.onClick = function (event, ui) {
|
|
var self=this;
|
|
console.debug('onClick',arguments);
|
|
|
|
var cardType = angular.element(ui.draggable).data('cards');
|
|
var card = _.find(this.cards,{key:cardType});
|
|
return this.play(card);
|
|
};
|
|
Game.prototype.onDrop = function (event, ui) {
|
|
var self=this;
|
|
console.debug('onDrop',arguments);
|
|
|
|
var cardType = angular.element(ui.draggable).data('cards');
|
|
var card = _.find(this.cards,{key:cardType});
|
|
return this.play(card);
|
|
};
|
|
Game.prototype.play = function (card) {
|
|
var self=this;
|
|
card.state.amount-=1;
|
|
|
|
var turn = this.lastCards.length-1;
|
|
var correct = this.test(card);
|
|
if (correct){
|
|
if(!this.incorrectCards[turn]) this.incorrectCards[turn]=[];
|
|
this.lastCards.push(angular.copy(card));
|
|
if(!this.incorrectCards[turn+1]) this.incorrectCards[turn+1]=[];
|
|
this.lab.state.score+=1;
|
|
} else {
|
|
// add incorrect one to sidelines
|
|
if (!this.incorrectCards[turn]) this.incorrectCards[turn]=[];
|
|
this.incorrectCards[turn].push(angular.copy(card));
|
|
|
|
// deal 2 random cards
|
|
_.sample(this.cards).state.amount+=1;
|
|
_.sample(this.cards).state.amount+=1;
|
|
this.lab.state.score-=2;
|
|
}
|
|
return correct;
|
|
};
|
|
/** Test the rule **/
|
|
Game.prototype.test = function (card) {
|
|
return this.rule.test(card,this.lastCards,this.cards);
|
|
};
|
|
Game.prototype.save = function () {
|
|
// Save every object's state to local storage
|
|
for (var key in this.allObjects) {
|
|
ObjectStorage.save(key, this.allObjects[key].state);
|
|
}
|
|
};
|
|
|
|
return Game;
|
|
}(Helpers, GameObjects, ObjectStorage,Rules,cards,achievements));
|
|
|
|
export default Game
|