<commit_before>
const BasicRule = require('../basic/BasicRule');

const Role = require('../../core/Player/Role');
const shuffle = require('../../util/shuffle');
const randsub = require('../../util/randsub');

function fillArray(arr, value, n) {
	for (let i = 0; i < n; i++) {
		arr.push(value);
	}
}

class StandardRule extends BasicRule {

	constructor() {
		super();

		this.candidateGeneralNum = 3;
	}

	async effect(driver) {
		await this.preparePlayers(driver);
		await this.prepareRoles(driver);
		await this.prepareSeats(driver);
		await this.prepareGenerals(driver);
		await this.prepareBattleField(driver);
		await this.prepareCards(driver);
		await this.proceed(driver);
	}

	prepareRoles(driver) {
		const players = driver.players;
		if (!players || players.length <= 1) {
			return;
		}
		shuffle(players);

		let rebelNum = Math.floor(players.length / 2);
		let loyalistNum = players.length - rebelNum - 1;
		let renegadeNum = 0;
		if (loyalistNum > 1) {
			renegadeNum++;
			loyalistNum--;
		}

		const roles = [];
		fillArray(roles, Role.Rebel, rebelNum);
		fillArray(roles, Role.Loyalist, loyalistNum);
		fillArray(roles, Role.Renegade, renegadeNum);
		shuffle(roles);
		roles.unshift(Role.Emperor);

		for (let i = 0; i < roles.length; i++) {
			players[i].setRole(roles[i]);
			players[i].updateProperty('role', roles[i]);
		}
	}

	async prepareGenerals(driver) {
		driver.loadCollection('standard');
		const generals = driver.createGenerals();

		// Set up the Emperor first
		const players = driver.players;
		const emperor = players.find(player => player.role() === Role.Emperor);
		await this.prepareEmperor(emperor, generals);
		const emperorGeneral = emperor.general();
		emperor.setKingdom(emperorGeneral.kingdom());
		emperor.broadcastProperty('kingdom', emperor.kingdom());
		emperor.broadcastProperty('general', emperorGeneral.toJSON());

		// Remove the Emperor's general from the candidate list
		for (let i = 0; i < generals.length; i++) {
			if (generals[i] === emperorGeneral) {
				generals.splice(i, 1);
				break;
			}
		}

		// Shuffle and set up others' generals
		shuffle(generals);
		const others = players.filter(player => player.role() !== Role.Emperor);
		await Promise.all(others.map(player => this.prepareGeneral(player, generals)));
		for (const player of others) {
			const general = player.general();
			if (general) {
				player.setKingdom(general.kingdom());
				player.broadcastProperty('kingdom', player.kingdom());
				player.broadcastProperty('general', general.toJSON());
			}
		}
	}

	async prepareEmperor(player, generals) {
		const candidates = generals.filter(general => general.isEmperor());

		const others = generals.filter(general => !general.isEmperor());
		candidates.push(...randsub(others, 2));

		const res = await player.askForGeneral(candidates, {num: 1});
		player.setGeneral(res[0]);
	}

	async prepareGeneral(player, generals) {
		const offset = this.candidateGeneralNum * (player.seat() - 2);
		const candidates = generals.slice(offset, offset + this.candidateGeneralNum);
		const res = await player.askForGeneral(candidates, {num: 1});
		player.setGeneral(res[0]);
	}

}

module.exports = StandardRule;
<commit_msg>Set hp and max hp at game start<commit_after>
const BasicRule = require('../basic/BasicRule');

const Role = require('../../core/Player/Role');
const shuffle = require('../../util/shuffle');
const randsub = require('../../util/randsub');

function fillArray(arr, value, n) {
	for (let i = 0; i < n; i++) {
		arr.push(value);
	}
}

class StandardRule extends BasicRule {

	constructor() {
		super();

		this.candidateGeneralNum = 3;
	}

	async effect(driver) {
		await this.preparePlayers(driver);
		await this.prepareRoles(driver);
		await this.prepareSeats(driver);
		await this.prepareGenerals(driver);
		await this.prepareBattleField(driver);
		await this.prepareCards(driver);
		await this.proceed(driver);
	}

	prepareRoles(driver) {
		const players = driver.players;
		if (!players || players.length <= 1) {
			return;
		}
		shuffle(players);

		let rebelNum = Math.floor(players.length / 2);
		let loyalistNum = players.length - rebelNum - 1;
		let renegadeNum = 0;
		if (loyalistNum > 1) {
			renegadeNum++;
			loyalistNum--;
		}

		const roles = [];
		fillArray(roles, Role.Rebel, rebelNum);
		fillArray(roles, Role.Loyalist, loyalistNum);
		fillArray(roles, Role.Renegade, renegadeNum);
		shuffle(roles);
		roles.unshift(Role.Emperor);

		for (let i = 0; i < roles.length; i++) {
			players[i].setRole(roles[i]);
			players[i].updateProperty('role', roles[i]);
		}
	}

	async prepareGenerals(driver) {
		driver.loadCollection('standard');
		const generals = driver.createGenerals();

		// Set up the Emperor first
		const players = driver.players;
		const emperor = players.find(player => player.role() === Role.Emperor);
		await this.prepareEmperor(emperor, generals);
		const emperorGeneral = emperor.general();
		emperor.setKingdom(emperorGeneral.kingdom());
		emperor.broadcastProperty('kingdom', emperor.kingdom());
		emperor.broadcastProperty('general', emperorGeneral.toJSON());

		// Remove the Emperor's general from the candidate list
		for (let i = 0; i < generals.length; i++) {
			if (generals[i] === emperorGeneral) {
				generals.splice(i, 1);
				break;
			}
		}

		// Shuffle and set up others' generals
		shuffle(generals);
		const others = players.filter(player => player.role() !== Role.Emperor);
		await Promise.all(others.map(player => this.prepareGeneral(player, generals)));
		for (const player of others) {
			const general = player.general();
			if (general) {
				player.setKingdom(general.kingdom());
				player.broadcastProperty('kingdom', player.kingdom());
				player.broadcastProperty('general', general.toJSON());
			}
		}
	}

	async prepareEmperor(player, generals) {
		const candidates = generals.filter(general => general.isEmperor());

		const others = generals.filter(general => !general.isEmperor());
		candidates.push(...randsub(others, 2));

		const res = await player.askForGeneral(candidates, {num: 1});
		const general = res[0];
		player.setGeneral(general);

		const hp = general.maxHp() + 1;
		player.setMaxHp(hp);
		player.setHp(hp);
		player.broadcastProperty('maxHp', hp);
		player.broadcastProperty('hp', hp);
	}

	async prepareGeneral(player, generals) {
		const offset = this.candidateGeneralNum * (player.seat() - 2);
		const candidates = generals.slice(offset, offset + this.candidateGeneralNum);
		const res = await player.askForGeneral(candidates, {num: 1});

		const general = res[0];
		player.setGeneral(general);

		const hp = general.maxHp();
		player.setMaxHp(hp);
		player.setHp(hp);
		player.broadcastProperty('maxHp', hp);
		player.broadcastProperty('hp', hp);
	}

}

module.exports = StandardRule;

{'fraction_non_alphanumeric': 0.1530385923406772, 'fraction_numerical': 0.004879491349992607, 'mean_word_length': 4.263813229571984, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 15, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5753859', 'n_tokens_mistral': 2477, 'n_tokens_neox': 2212, 'n_words': 478}