Simulated rules so they are winnable, added win and lose

This commit is contained in:
2016-02-29 17:16:40 +08:00
parent 2a02b4e69f
commit f94973c43c
13 changed files with 360 additions and 494 deletions
+1 -1
View File
@@ -49,7 +49,7 @@ var analytics = module.exports =
ga('create', Helpers.analytics,'auto');
ga('set', { 'appName': 'Cards For Science', 'appId': '', 'appVersion': '0.6' });
ga('set', 'anonymizeIp', true);
ga('send','pageview');
// ga('send','pageview');// angulartics
}
+111 -78
View File
@@ -7,13 +7,14 @@
var jquery = require("jquery");
var jqueryUi = require("jquery-ui");
var jqueryUiTouchPunch = require("jquery-ui-touch-punch");
var jqueryCookie = require("js-cookie");
var jsCookie = require("js-cookie");
var angular = require("angular");
var angularDragdrop = require("angular-dragdrop");
var angularAnimate = require("angular-animate");
var angulartics = require('angulartics');
var angularticsGoogleAnalytics = require('angulartics-google-analytics');
var ngAlertify = require("alertify.js/dist/js/ngAlertify.js");
//app
var ObjectStorage = require("js/storage");
@@ -22,11 +23,12 @@ var GameObjects = require("js/gameobjects");
var analytics = require("js/analytics");
var Game = require("js/game");
var Rules = require("js/rules.js");
var UI = require("js/ui.js");
var app = (function (Helpers,analytics,Game,Rules) {
Helpers.validateSaveVersion();
var app = angular.module('cardsForScience', ['ngDragDrop','ngAnimate','angulartics', angularticsGoogleAnalytics]);
var app = angular.module('cardsForScience', ['ngDragDrop','ngAnimate','angulartics', angularticsGoogleAnalytics,"ngAlertify"]);
// config
app.config(function ($analyticsProvider) {
@@ -160,7 +162,7 @@ var app = (function (Helpers,analytics,Game,Rules) {
game.lab = lab;
game.allObjects.lab = lab;
var promise = game.load($http, $q);
game.init();
game.reset();
// return promise;
return game;
};
@@ -259,8 +261,8 @@ var app = (function (Helpers,analytics,Game,Rules) {
function TableController($scope, game, lab, $filter) {
var vm = this;
vm.cards = detector.cards;
vm.rule = '';
vm.hints = [];
vm.ruleInfo = game.ruleInfo;
vm.hints = game.hints;
vm.limit = -12;
vm.hintCost = 10;
vm.ruleCost = 300;
@@ -279,8 +281,10 @@ var app = (function (Helpers,analytics,Game,Rules) {
var result = game.onDrop(event, ui, game);
};
vm.revealRule = function () {
vm.rule = game.rule.describe();
lab.state.score -= vm.ruleCost;
if (vm.ruleInfo.length===0){
vm.ruleInfo.push(game.rule.describe());
lab.state.score -= vm.ruleCost;
};
};
vm.revealHint = function () {
var hint = game.rule.nextHint();
@@ -294,61 +298,17 @@ var app = (function (Helpers,analytics,Game,Rules) {
app.controller('TableController', TableController);
function LabController($interval, game, lab) {
// todo give workers instead of game
var vm = this;
vm.lab = lab;
vm.showDetectorInfo = function () {
if (!vm._detectorInfo) {
vm._detectorInfo = Helpers.loadFile('html/detector.html');
}
UI.showModal('Detector', vm._detectorInfo);
};
};
LabController.$inject = ['$interval', 'game', 'lab'];
app.controller('LabController', LabController);
function RulesController($scope, game, lab) {
function RulesController($scope, game, lab,$analytics,alertify) {
var vm = this;
// present just a few hypothesis
var rules = Rules.rules.map(function (r) {
return angular.copy(r);
// emit event track (with category and label properties for GA)
$analytics.eventTrack('rule', {
category: 'rule', label: game.rule.describe()
});
rules = _.sampleSize(rules, 2);
if (!_.find(rules, {
description: game.rule.description
})) {
var rule = angular.copy(game.rule);
rule.setOptions({}); // reset the value of this copy to not give away;
rules.push(rule);
} else {
rules.push(angular.copy(_.sample(Rules.rules)));
}
vm.rules = _.shuffle(rules);
// or present them without options?
var rules2 = Rules.rules.map(function (r) {
var rule = angular.copy(r);
rule.randomize();
return rule;
});
rules2 = _.sampleSize(rules, 4);
// add the real rule and a couple of variations
var rule = angular.copy(game.rule);
rules2.push(rule);
var rule = angular.copy(game.rule);
rule.randomize();
rules2.push(rule);
var rule = angular.copy(game.rule);
rule.randomize();
rules2.push(rule);
// clean and add to controller
rules2 = _.uniq(rules2);
rules2 = _.shuffle(rules2);
vm.rules2 = rules2;
vm.hypotheses = game.hypotheses;
vm.upgrades = game.upgrades;
vm.isVisible = function (upgrade) {
@@ -357,15 +317,10 @@ var app = (function (Helpers,analytics,Game,Rules) {
vm.isAvailable = function (upgrade) {
return upgrade.isAvailable(lab, game.allObjects);
};
vm.upgrade = function (upgrade) {
if (upgrade.buy(lab, game.allObjects)) {
UI.showUpdateValue("#update-funding", upgrade.cost);
}
};
/** return a class based on none right or wrong guessed **/
vm.isGuessed = function(rule){
if (rule.state.guessed===true) return 'bg-success';
else if (rule.state.guessed===false) return 'bg-danger';
if (rule.guessed===true) return 'bg-success';
else if (rule.guessed===false) return 'bg-danger';
else return '';
};
@@ -377,17 +332,47 @@ var app = (function (Helpers,analytics,Game,Rules) {
if (sameRule && sameOpts) {
// right!
lab.state.score += 200;
lab.state.rulesGuessed.push({
key: game.rule.key,
options: game.rule.options,
description: game.rule.describe(),
});
if (!rule.state) rule.state={};
rule.state.guessed=true;
rule.guessed=true;
alertify.alert(
'You have won using inductive logic! <p> <p> Play again?',
function(event){
event.preventDefault();
// ObjectStorage.clear();
// $window.location.reload(true); /// reloads are better for ads?
game.reset();
// since this confirmation was away from the dom we need to
// manually refresh
$scope.$apply();
},function(){}
);
} else {
lab.state.score -= 200;
rule.state.guessed=false;
rule.guessed=false;
lab.state.rulesFailed.push({
key: rule.key,
options: rule.options,
description: rule.describe(),
});
}
console.log('guess', arguments);
// vm.winDialouge = function () {
// if (!vm._winDialouge) {
// vm._winDialouge = Helpers.loadFile('html/win.html');
// }
// UI.showModal('Win', vm._winDialouge);
// };
};
};
RulesController.$inject = ['$scope', 'game', 'lab'];
RulesController.$inject = ['$scope', 'game', 'lab','$analytics','alertify'];
app.controller('RulesController', RulesController);
function AchievementsController($scope, game, lab) {
@@ -402,35 +387,83 @@ var app = (function (Helpers,analytics,Game,Rules) {
AchievementsController.$inject = ['$scope', 'game', 'lab'];
app.controller('AchievementsController', AchievementsController);
function SaveController($scope, $interval, $window, game, lab) {
function SaveController($scope, $interval, $window, alertify, game, lab) {
var vm = this;
game.lastSaved = new Date().getTime();
vm.lastSaved = game.lastSaved;
;
vm.saveNow = function () {
var saveTime = new Date().getTime();
lab.state.time += saveTime - game.lastSaved;
game.save();
game.lastSaved = saveTime;
vm.lastSaved = game.lastSaved;
// if (lab.state.score<0){
// alertify.alert(
// 'Your score is below zero, so you lost :( Want to try a different rule?',
// function(event){
// event.preventDefault();
// // ObjectStorage.clear();
// // $window.location.reload(true); /// reloads are better for ads?
// game.reset();
// // since this confirmation was away from the dom we need to
// // manually refresh
// $scope.$apply();
// },function(){}
// );
// }
};
vm.restart = function () {
if ($window.confirm(
'Do you really want to restart the game? All progress will be lost.'
)) {
ObjectStorage.clear();
$window.location.reload(true);
}
console.log('restart');
alertify.confirm(
'Do you really want to restart the game? All progress will be lost.',
function(event){
event.preventDefault();
// ObjectStorage.clear();
// $window.location.reload(true); /// reloads are better for ads?
game.reset();
// since this confirmation was away from the dom we need to
// manually refresh
$scope.$apply();
},function(){}
);
};
$interval(vm.saveNow, 10000);
};
SaveController.$inject = ['$scope', '$interval', '$window', 'game', 'lab'];
SaveController.$inject = ['$scope', '$interval', '$window', 'alertify', 'game', 'lab'];
app.controller('SaveController', SaveController);
function StatsController($scope, lab) {
function StatsController($scope, lab,game,alertify) {
var vm = this;
vm.lab = lab;
vm.lost=false;
$scope.$watch('lc.lab.state.score', function (newValue, oldValue) {
if (newValue<0&&!vm.lost){
vm.lost=true;
alertify.alert(
'<p>You lost :( <p> Play again? <p><p>P.S. The rule was: <p>"'+game.rule.describe()+'"',
function(event){
event.preventDefault();
// ObjectStorage.clear();
// $window.location.reload(true); /// reloads are better for ads?
game.reset();
// since this confirmation was away from the dom we need to
// manually refresh
$scope.$apply();
vm.lost=false;
},function(){}
);
};
});
};
StatsController.$inject = ['$scope', 'lab'];
StatsController.$inject = ['$scope', 'lab','game','alertify'];
app.controller('StatsController', StatsController);
analytics.init();
+96 -68
View File
@@ -7,6 +7,7 @@ var GameObjects = require("js/gameobjects.js");
var Rules = require("js/rules.js");
var cards = require("json/cards.json");
var achievements = require("json/achievements.json");
var ruleSimulations = require("json/simulations.json");
var Game = module.exports =(function (Helpers, GameObjects, ObjectStorage,Rules,cards,achievements) {
'use strict';
@@ -21,11 +22,13 @@ var Game = module.exports =(function (Helpers, GameObjects, ObjectStorage,Rules,
// lab: this.lab
};
this.loaded = false;
this.rules = Rules.rules;
this.rule=undefined;
this.hypotheses = [];
this.lastCards= [];
this.hints=[];
this.ruleInfo=[];
this.incorrectCards= [];
this.rule=undefined;
this.rules=Rules.rules;
this.Rule=Rules.Rule;
};
@@ -36,56 +39,9 @@ var Game = module.exports =(function (Helpers, GameObjects, ObjectStorage,Rules,
return;
}
// I know synchronous requests are bad as they will block the browser.
// However, I don't see any other reasonable way to do this in order to
// make it work with Angular. If you know a way, let me know, and I'll
// give you a beer. - Kevin
this.cards = cards; //Helpers.loadFile('json/cards.json');
this.achievements = require("json/achievements.json"); //Helpers.loadFile('./json/achievements.json');
// function successCallback(response) {
// return angular.fromJson(response.data);
// }
//
// function errorCallback(response) {
// return console.error('Could not get url', response.statusText, response);
// }
// return $q.all(
// $http.get('json/cards.json', {
// transformResponse: angular.fromJson
// })
// .then(function (response) {
// return self.cards = response.data;
// }),
// $http.get('json/workers.json', {
// transformResponse: angular.fromJson
// })
// .then(function (response) {
// return self.workers = response.data;
// }),
// $http.get('json/upgrades.json', {
// transformResponse: angular.fromJson
// })
// .then(
// function (response) {
// return self.upgrades = response.data;
// }),
// $http.get('json/achievements.json', {
// transformResponse: angular.fromJson
// })
// .then(
// function (response) {
// return self.achievements = response.data;
// }),
// $http.get('json/keywords.json', {
// transformResponse: angular.fromJson
// })
// .then(
// function (response) {
// return self.keywords = response.data;
// })
// ).then(function () {
// 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
@@ -102,54 +58,126 @@ var Game = module.exports =(function (Helpers, GameObjects, ObjectStorage,Rules,
function (a) {
return makeGameObject(GameObjects.Achievement, a);
});
// Load states from local store
for (var key in self.allObjects) {
var o = self.allObjects[key];
o.loadState(ObjectStorage.load(key));
}
// 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.init = function () {
Game.prototype.reset = function () {
// setup game
this.rule = _.sample(Rules.rules);
this.rule.randomize();
this.rule = this.newRule();
// check if we have any cards in hand
// var totalElements = _(self.cards).map('state.amount').sum();
// if (totalElements<1) self.dealHand();
this.dealHand();
// deal first card
// TODO make sure these follow rule
// deal new initial cards
this.lastCards.splice(0,this.lastCards.length);
this.lastCards.push.apply(this.lastCards,_.sampleSize(this.cards,3));
for (var i = 0; i < this.lastCards.length; i++) {
this.incorrectCards[i]=[];
}
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;
return self;
// 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 < 3; 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 () {
var okRules = _.filter(ruleSimulations,function(s){
return s.ratioRight>0.1&&s.ratioRight<0.6;
});
// 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 hand=_.sampleSize(this.cards,n);
var sample=_.sampleSize(this.cards,n);
// empty all cards
this.cards.map(function(card){
card.state.amount=0;
});
for (var i = 0; i < hand.length; i++) {
var card = hand[i];
// 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;
+1 -106
View File
@@ -29,7 +29,7 @@ var GameObjects = module.exports = (function () {
}
return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
s4() + '-' + s4() + s4() + s4();
}
};
/** @class Lab
*/
@@ -254,109 +254,6 @@ var GameObjects = module.exports = (function () {
return this.state.amount -= 1;
};
/** @class Worker
* Implement an auto-clicker in the game.
*/
var Worker = function (obj) {
GameObject.apply(this, [obj]);
this.state.hired = 0;
};
Worker.prototype = Object.create(GameObject.prototype);
Worker.prototype.constructor = Worker;
Worker.prototype.isVisible = function (lab) {
if (!lab) {
return false;
}
return this.state.hired > 0 ||
lab.state.money >= this.state.cost * GLOBAL_VISIBILITY_THRESHOLD;
};
Worker.prototype.isAvailable = function (lab) {
if (!lab) {
return false;
}
return lab.state.money >= this.state.cost;
};
Worker.prototype.hire = function (lab) {
if (lab && lab.buy(this.state.cost)) {
this.state.hired++;
var cost = this.state.cost;
this.state.cost = Math.floor(cost * this.cost_increase);
return cost;
}
return -1; // not enough money
};
Worker.prototype.getTotal =
function () {
return this.state.hired * this.state.rate;
};
/** @class Upgrade
*/
var Upgrade = function (obj) {
GameObject.apply(this, [obj]);
this.state.visible = false;
this.state.used = false;
};
Upgrade.prototype = Object.create(GameObject.prototype);
Upgrade.prototype.constructor = Upgrade;
Upgrade.prototype.meetsRequirements = function (allObjects) {
if (!allObjects) {
return false;
}
for (var i = 0; i < this.requirements.length; i++) {
var req = this.requirements[i];
if (allObjects[req.key].state[req.property] < req.threshold) {
return false;
}
}
return true;
};
Upgrade.prototype.isAvailable = function (lab, allObjects) {
if (!lab || !allObjects) {
return false;
}
return !this.state.used && lab.state.money >= this.cost &&
this.meetsRequirements(allObjects);
};
Upgrade.prototype.isVisible = function (lab, allObjects) {
if (!lab || !allObjects) {
return false;
}
if (!this.state.used &&
(this.state.visible ||
lab.state.money >= this.cost * GLOBAL_VISIBILITY_THRESHOLD &&
this.meetsRequirements(allObjects))) {
this._visible = true;
return true;
}
return false;
};
Upgrade.prototype.buy = function (lab, allObjects) {
if (lab && allObjects && !this.state.used && lab.buy(this.cost)) {
for (var i = 0; i < this.targets.length; i++) {
var t = this.targets[i];
allObjects[t.key].state[t.property] *= this.factor || 1;
allObjects[t.key].state[t.property] += this.constant || 0;
}
this.state.used = true; // How about actually REMOVING used upgrades?
this.state.visible = false;
return this.cost;
}
return -1;
};
/** @class Achievement
*/
@@ -394,8 +291,6 @@ var GameObjects = module.exports = (function () {
return {
Lab: Lab,
Card: Card,
Worker: Worker,
Upgrade: Upgrade,
Achievement: Achievement,
Cards: Cards
};
+75 -63
View File
@@ -5,7 +5,7 @@
if (!module) module=function(){};
var chai;
if (!chai){
chair = require("chai");
chai = require("chai");
}
/**
@@ -16,11 +16,41 @@ if (!chai){
var Rules = module.exports = (function functionName(_,chai) {
/** Generate all combination of arguments from array using functional programming instead of recursive
* @param {Object} opts - An array or arrays with keys describing options [['Ben','Jade','Darren'],['Smith','Miller']]
* @returns {Array} - An array of arrays e.g. [['Ben','Smith'],[..]]
**/
function cartesianProductOf(opts) {
if (arguments.length>1) opts=arguments;
return _.reduce(opts, function(a, b) {
return _.flatten(_.map(a, function(x) {
return _.map(b, function(y) {
return x.concat([y]);
});
}), true);
}, [ [] ]);
};
/** Generate all combination of arguments from objects using functional programming instead of recursive
* @param {Object} opts - An object or arrays with keys describing options {firstName:['Ben','Jade','Darren'],lastName:['Smith','Miller']}
* @returns {Array} - An array of objects e.g. [{firstName:'Ben',LastName:'Smith'},{..]
**/
function cartesianProductObj(optObj){
var opts = _.values(optObj);
var keys = _.keys(optObj);
var combs = cartesianProductOf(opts);
return _.map(combs,function(comb){
return _.zipObject(keys,comb);
});
}
/**
* Rule prototype
* @param {String} key A short key
* @param {String} description Description of the rule using angular templating from options
* @param {Function} ruleFunc A function returning a true or a failure message or a error
* @param {Function} ruleFunc A function returning a true or a failure message or a assertion error
* @param {Object} optionDefaults Default options for the rule e.g. {n:1, parameter:'color'}.
* @param {Object} optionDesc Object with object for each option
* @param {Array} optionDesc[].possibleVals Array of possible values or empty if they are to many to be enumerated
@@ -30,23 +60,44 @@ var Rules = module.exports = (function functionName(_,chai) {
* `The rule uses <%= parameter %>` and for every parameter you can
* use `The rule doesn't use <%= parameterUnused %>` to have each unused param substituted in.
*/
var Rule = function (description, ruleFunc, optionDefaults, optionDesc, hintTmpls) {
var Rule = function (key, description, ruleFunc, optionDefaults, optionDesc, hintTmpls) {
// check inputs
if (!(typeof (description) === 'string' || description instanceof String) || !description.length)
throw new TypeError('description should be a non empty string');
throw new TypeError('Description should be a non empty string');
this.description = description;
if (!(ruleFunc instanceof Function))
throw new TypeError('ruleFunc should be a function');
this.key=key;
this.ruleFunc = ruleFunc;
this.optionDesc = optionDesc || {};
this.options = this.optionDefaults = optionDefaults || {};
this.hintTmpls = hintTmpls || [];
// init
this.state = {};
this.hintsUsed = 0;
this.state = {
hintsUsed: 0,
wrongCards: 0,
rightCards: 0,
wrongGuesses: 0,
rightGuesses: 0,
};
// used for template rendering
this.otherOptions={nth:this.nth,lastn:this.lastn};
// render hint templates
this.hints = this.genHints();
// work out all option combos, only takes a second
this.optionsPossible=this.genOptions();
};
Rule.prototype.genOptions = function () {
var possibleVals={};
for (var prop in this.optionDesc) {
if (this.optionDesc.hasOwnProperty(prop)) {
possibleVals[prop]=this.optionDesc[prop].possibleVals;
}
}
return this.optionsPossible=cartesianProductObj(possibleVals);
};
Rule.prototype.setOptions = function (options) {
this.options = _.defaults(options, this.optionDefaults);
@@ -98,56 +149,6 @@ var Rules = module.exports = (function functionName(_,chai) {
Rule.prototype.describe = function () {
return this.describeVariation(this.options);
};
// Rule.prototype.describeHtml = function (arguments) {
// // we want template params where each options is replace with a select box
// var tmplParams = {};
//
// for (var option in this.optionDesc) {
// if (this.optionDesc.hasOwnProperty(option)) {
// var vals = this.optionDesc[option].possibleVals;
// if (vals) {
// s = '<select name="' + option + '" ng-model="rule.options.' + option + '" class="form-control input-sm">\n';
// for (var i = 0; i < vals.length; i++) {
// s += '<option value="' + vals[i] + '">' + vals[i] + '</option>\n';
// }
// s += '</select>\n';
// tmplParams[option] = s;
// } else {
// tmplParams[option] = option;
// }
// }
// }
// return _.template(this.description)(tmplParams);
// };
/** Generate angular template for this rule **/
// Rule.prototype.describeNg = function (arguments) {
//
// // first put option name into this option template
// // _.templateSettings.interpolate = /<%=([\s\S]+?)%>/g;
// optionTmpl = '' +
// '<select name="<%=option%>" type="number" ng-model="rule.options.<%=option%>" class="form-control input-sm">\n' +
// '<option ng-repeat="v in rule.optionDesc.<%=option%>.possibleVals" value="{{v}}">{{v}}</option>\n' +
// '</select>\n';
//
// // we want template params where each options is replace with a select box
// var tmplParams = {};
//
// for (var option in this.optionDesc) {
// if (this.optionDesc.hasOwnProperty(option)) {
// var vals = this.optionDesc[option].possibleVals;
// if (vals) {
// tmplParams[option] = _.template(optionTmpl)({
// option: option
// });
// } else {
// tmplParams[option] = option;
// }
// }
// }
//
// // now in description replace params with select box
// return _.template(this.description)(tmplParams);
// };
/** Compile description using options to express rule**/
Rule.prototype.describeVariation = function (options) {
var compiled = _.template(this.description);
@@ -191,15 +192,15 @@ var Rules = module.exports = (function functionName(_,chai) {
};
/** Get next hint **/
Rule.prototype.nextHint = function () {
var hint = this.hints[this.hintsUsed];
this.hintsUsed++;
var hint = this.hints[this.state.hintsUsed];
this.state.hintsUsed++;
return hint || "";
};
/** Generate an automatic hint from params **/
Rule.prototype.genHints = function () {
// first manual hints
this.hintsUsed = 0;
this.state.hintsUsed = 0;
var hints = [];
// compile hints for each unused property
@@ -226,7 +227,7 @@ var Rules = module.exports = (function functionName(_,chai) {
for (var optionUnused in unusedOptions) {
if (unusedOptions.hasOwnProperty(optionUnused)) {
// find hint templats that take this unused option
// find hint templates that take this unused option
for (var i = 0; i < this.hintTmpls.length; i++) {
var tmpl = this.hintTmpls[i];
if (tmpl.indexOf(optionUnused) >= 0) {
@@ -250,8 +251,8 @@ var Rules = module.exports = (function functionName(_,chai) {
}
// on on a last hint
hints.push("That's all the hints for this rule. But don't forget to check for hints for the overall game. This is a game of inductive logic to try to disprove rules.");
hints.push("You cheeky blighter. Feel free to restart the game to get a new rule if this one is no fun (it will happen).");
hints.push("That's all the hints. But this is a game of inductive logic so try to disprove rules instead of proving them.");
hints.push("No more hints you cheeky blighter!");
// and finally remove duplicate hints
hints = _.uniq(hints);
@@ -299,6 +300,11 @@ var Rules = module.exports = (function functionName(_,chai) {
}
};
Rule.prototype.loadState =
function (state) {
$.extend(this.state, state);
};
// Now defined actual rules
var rules = [];
@@ -307,6 +313,7 @@ var Rules = module.exports = (function functionName(_,chai) {
// here is a example rule where the card must have differen't color etc from the last card
// but it's abstracted to allow variations
new Rule(
"d4a2f61a-0fb9-4eb6-9258-3e14ae4cd512",
"Next card must not have the same <%= property %> as the <%= lastn(n) %> card",
function (card, lastCards, allCards, options) {
var lastNCard = lastCards[lastCards.length - this.options.n];
@@ -336,10 +343,10 @@ var Rules = module.exports = (function functionName(_,chai) {
]
),
new Rule(
"2b70bd6a-8bdd-49d4-bec7-bfb9de090e78",
"If <%= lastn(n) %> cards value was between <%= min %> and <%= max %> play a card that isn't and vice versa.",
function (card, lastCards, allCards, options) {
var lastNCard = lastCards[lastCards.length - this.options.n];
var property = this.options.property;
var lastWasbetween = options.min < lastNCard.value && lastNCard.value < options.max;
if (lastWasbetween)
return chai.expect(card)
@@ -382,6 +389,7 @@ var Rules = module.exports = (function functionName(_,chai) {
]
),
new Rule(
"3e12d713-335a-42e7-81ed-7064442f628a",
"Play a card with a value <%= min %> to <%= max %> higher than the value of the <%= lastn(n) %> card. The numbers wrap around once they reach the max",
function (card, lastCards, allCards, options) {
var lastNCard = lastCards[lastCards.length - this.options.n];
@@ -426,6 +434,7 @@ var Rules = module.exports = (function functionName(_,chai) {
new Rule(
"99b1d408-000d-41e6-8a0c-886a5d21d06f",
"If the <%= lastn(n) %> card is an even-valued card, play a <%= evenColor %> card. Otherwise play the other color",
function (card, lastCards, allCards, options) {
var lastNCard = lastCards[lastCards.length - this.options.n];
@@ -465,6 +474,7 @@ var Rules = module.exports = (function functionName(_,chai) {
),
new Rule(
"4014c459-a7a7-4a49-98f5-302a1b7b89e7",
"Play a card that has the same <%= property %> or color as the <%= lastn(n) %> card but not both.",
function (card, lastCards, allCards, options) {
var lastNCard = lastCards[lastCards.length - options.n];
@@ -495,6 +505,7 @@ var Rules = module.exports = (function functionName(_,chai) {
),
new Rule(
"793d93cb-ca09-4cda-8781-6fce02edf09c",
"If the <%= lastn(n) %> card's number is higher than <%= min %>, change <%= property %>, and if lower, keep it the same.",
function (card, lastCards, allCards, options) {
var lastNCard = lastCards[lastCards.length - options.n];
@@ -540,6 +551,7 @@ var Rules = module.exports = (function functionName(_,chai) {
]
),
new Rule(
"f4fba793-f886-4db8-9853-240002bb112e",
"If the <%= lastn(n) %> card was a <%= property %> card, play a higher value card otherwise lower.",
//TODO what if we have a high card? we can only go higher
function (card, lastCards, allCards, options) {
-19
View File
@@ -1,19 +0,0 @@
/** Extend chai to be used in defining rules **/
// might want to use chair string for startswith etc
// chai-properties for muliple properties
// chai-adhoc for easier additions https://github.com/AnAppAMonth/chai-adhoc
var chai = (function functionName(chai) {
// wrap every chainer to add message to chain? that would be interesting
// card method that set's name of card?
// wrap or overide property chain to add to name
// and methods to compare to Nth last card's property
// and what about more complex ones like mod and odd and prime
})(chai);
+1 -1
View File
@@ -89,7 +89,7 @@ var UI = module.exports = (function (FastClick,Cookies) {
if (typeof Cookies.get('cookielaw') === 'undefined') {
var alert = '<div id="cookielaw" class="alert alert-info" role="alert">';
alert += '<button type="button" class="btn btn-primary">OK</button>';
alert += '<i class="fa fa-info-circle alert-glyph"></i> <span class="alert-text">Particle Clicker uses local storage to store your current progress.</span>';
alert += '<i class="fa fa-info-circle alert-glyph"></i> <span class="alert-text">Cards for science uses local storage to store your current progress.</span>';
alert += '</div>';
alert = $(alert);
alert.find('button').click(function ()